Doc. no: N4332 Date: 2014-11-21 Revises: N4243 Reply-To: Christopher Kohlhoff <chris@kohlhoff.com>
In the June 2014 committee meeting in Rapperswil, LEWG requested that Boost.Asio-based N2175 Networking Library Proposal for TR2 (Revision 1) be updated for C++14 and brought forward as a proposed Networking Technical Specification. This document is that revision. As well as updating the proposal for C++14, it incorporates improvements to Asio that are based on the widespread field experience accumulated since 2007.
The Boost.Asio library, from which this proposal is derived, has been deployed in numerous systems, from large (including internet-facing HTTP servers, instant messaging gateways and financial markets applications) to small (mobile phones and embedded systems). The Asio library supports, or has been ported to, many operating systems including Linux, Mac OS X, Windows (native), Windows Runtime, Solaris, FreeBSD, NetBSD, OpenBSD, HP-UX, Tru64, AIX, iOS, Android, WinCE, Symbian, vxWorks and QNX Neutrino.
Revision 3 addresses issues raised by LEWG in Urbana and includes the following changes:
string_view
where appropriate.
An almost complete implementation of the proposal text may be found in a variant of Asio that stands alone from Boost. This variant is available at https://github.com/chriskohlhoff/asio/tree/master.
Unfamiliar readers are encouraged to look to the Boost.Asio documentation and examples for a more complete picture of the use of the libary.
However, to give some idea of the flavour of the proposed library, consider the following sample code. This is part of a server program that echoes the characters it receives back to the client in upper case.
template <typename Iterator> void uppercase(Iterator begin, Iterator end) { std::locale loc(""); for (Iterator iter = begin; iter != end; ++iter) *iter = std::toupper(*iter, loc); } void sync_connection(tcp::socket& socket) { try { std::vector<char> buffer_space(1024); for (;;) { std::size_t length = socket.read_some(buffer(buffer_space)); uppercase(buffer_space.begin(), buffer_space.begin() + length); write(socket, buffer(buffer_space, length)); } } catch (std::system_error& e) { // ... } }
The synchronous operations used above are functions that do not return control to the caller until the corresponding operating system operation completes. In Asio-based programs their use cases typically fall into two categories:
Next, the equivalent code developed using asynchronous operations might look something like this:
class async_connection : public std::enable_shared_from_this<async_connection> { public: async_connection(tcp::socket socket) : socket_(std::move(socket)) { } void start() { do_read(); } private: void do_read() { auto self(shared_from_this()); socket_.async_read_some(buffer(buffer_space_), [this, self](std::error_code ec, std::size_t length) { if (!ec) { uppercase(buffer_space_.begin(), buffer_space_.begin() + length); do_write(length); } }); } void do_write(std::size_t length) { auto self(shared_from_this()); async_write(socket_, buffer(buffer_space_, length), [this, self](std::error_code ec, std::size_t /*length*/) { if (!ec) { do_read(); } }); } tcp::socket socket_; std::vector<char> buffer_space_{1024}; };
Asynchronous operations do not block the caller, but instead involve the delivery of a notification to the program when the corresponding operating system operation completes. Most non-trivial Asio-based programs will make use of asynchronous operations.
While the code may appear more complex due to the inverted flow of control, it allows a knowledgeable programmer to write code that will scale to a great many concurrent connections. However, this proposal uses the asynchronous model described in [N4045]. This is an extensible model that allows the asynchronous operations to support a variety of composition and notification mechanisms, and these mechanisms may alleviate this complexity. This includes futures:
std::future<std::size_t> fut = socket.async_read_some(buffer(buffer_space), use_future); // ... std::size_t length = fut.get();
and, through library extensions, coroutines:
void coro_connection(tcp::socket& socket, yield_context yield) { try { std::vector<char> buffer_space(1024); for (;;) { std::size_t length = socket.async_read_some(buffer(buffer_space), yield); uppercase(buffer_space.begin(), buffer_space.begin() + length); async_write(socket, buffer(buffer_space, length), yield); } } catch (std::system_error& e) { // ... } }
Finally, for many applications, networking is not a core feature, nor is it seen as a core competency of the application’s programmers. To cater to these use cases, the proposal provides a high-level interface to TCP sockets that is designed around the familiar C++ I/O streams framework.
Using the library in this way is as easy as opening a stream object with the remote host’s details:
tcp::iostream s("www.boost.org", "http");
Once connected, you send and receive any data as needed. In this case you send a request:
s << "GET / HTTP/1.0\r\n"; s << "Host: www.boost.org\r\n"; s << "Accept: */*\r\n"; s << "Connection: close\r\n\r\n";
Then receive and process the response:
std::string header; while (std::getline(s, header) && header != "\r") std::cout << header << "\n"; std::cout << s.rdbuf();
You can set a timeout to detect unresponsive connections:
s.expires_after(std::chrono::seconds(60));
And, if at any time there is an error, the tcp::iostream
class’s error()
member function may be used to obtain an error_code
that identifies the reason for failure:
if (!s) { std::cout << "Unable to connect: " << s.error().message() << "\n"; return 1; }
Problem areas addressed by this proposal include:
Features that are considered outside the scope of this proposal include:
The bulk of the library interface is intended for use by developers with at least some understanding of networking concepts (or a willingness to learn). A high level iostreams interface supports simple use cases and permits novices to develop network code without needing to get into too much depth.
The interface is based on the BSD sockets API, which is widely implemented and supported by extensive literature. It is also used as the basis of networking APIs in other languages (e.g. Java). Unsafe practices of the BSD sockets API, e.g. lack of compile-time type safety, are not included.
Asynchronous support is derived from the Proactor design pattern as implemented by the ADAPTIVE Communication Environment [ACE], and is influenced by the design of the Symbian C++ sockets API [SYMBIAN], which supports synchronous and asynchronous operations side-by-side. The Microsoft .NET socket classes [MS-NET] and the Extended Sockets API [ES-API] developed by The Open Group support similar styles of network programming.
This is a pure library proposal. It does not add any new language features, nor does it alter any existing standard library headers. It makes additions to experimental headers that may also be modified by other Technical Specifications.
This library can be implemented using compilers that conform to the C++14 standard. An implementation of this library requires operating system-specific functions that lie outside the C++14 standard.
The asynchronous operations defined in this proposal use the asynchronous model described in [N4045]. With the extensible asynchronous model presented in that paper, the user has the ability to select an asynchronous approach that is appropriate to each use case. With these library foundations, a single extensible asynchronous model can support a variety of composition methods, including:
To facilitate the coordination of asynchronous operations in multithreaded programs, the asynchronous model also utilises the executors design described in [N4046].
As executors and the extensible asynchronous model are a prerequisite for the networking library, the proposed text below incorporates a complete specification of these facilities.
<experimental/executor>
synopsishandler_type
async_result
async_completion
associated_allocator
get_associated_allocator
execution_context
execution_context::service
is_executor
uses_executor
associated_executor
get_associated_executor
executor_wrapper
wrap
executor_work
make_work
system_executor
bad_executor
executor
dispatch
post
defer
strand
use_future_t
async_result
for
packaged_task
packaged_handler
packaged_token
package
<experimental/buffer>
synopsismutable_buffer
const_buffer
mutable_buffers_1
const_buffers_1
buffer_cast
buffer_size
buffer_copy
dynamic_vector_buffer
dynamic_string_buffer
transfer_all
transfer_at_least
transfer_exactly
<experimental/socket>
synopsissocket_base
socket_base::linger
basic_socket
basic_datagram_socket
basic_stream_socket
basic_socket_acceptor
<experimental/internet>
synopsisip::address
ip::address_v4
ip::address_v6
ip::bad_address_cast
ip::address_cast
ip::address_iterator_v4
ip::address_iterator_v6
ip::address_range_v4
ip::address_range_v6
ip::network_v4
ip::network_v6
ip::basic_endpoint
ip::resolver_query_base
ip::basic_resolver_entry
ip::basic_resolver_iterator
ip::basic_resolver_query
ip::basic_resolver
ip::tcp
ip::tcp::no_delay
ip::udp
ip::v6_only
ip::unicast::hops
ip::multicast::outbound_interface
ip::multicast::hops
ip::multicast::enable_loopback
This clause describes components that C++ programs may use to perform network operations.
The following subclauses describe components for executors, I/O services, timers, buffer management, sockets, endpoint resolution, iostreams, and internet protocols, as summarized in the table below:
Table 1. Networking library summary
Subclause |
Header(s) |
---|---|
| |
| |
| |
| |
| |
| |
| |
|
Throughout this clause, the names of the template parameters are used to express type requirements, as listed in the table below.
Table 2. Template parameters and type requirements
template parameter name |
type requirements |
---|---|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
See section 3.194 of POSIX Base Definitions, Host Byte Order.
See section 3.238 of POSIX Base Definitions, Network Byte Order.
A synchronous operation is logically executed in the context of the initiating thread. Control is not returned to the initiating thread until the operation completes.
An asynchronous operation is logically executed in parallel to the context of the initiating thread. Control is returned immediately to the initiating thread without waiting for the operation to complete. Multiple asynchronous operations may be executed in parallel by a single initiating thread.
Synchronous network library functions often provide two overloads, one
that throws an exception to report system errors, and another that sets
an error_code
.
[Note: This supports two common use cases:
— Uses where system errors are truly exceptional and indicate a serious
failure. Throwing an exception is the most appropriate response. This is
the preferred default for most everyday programming.
— Uses
where system errors are routine and do not necessarily represent failure.
Returning an error code is the most appropriate response. This allows application
specific error handling, including simply ignoring the error.
—end note]
Functions not having an argument of type
error_code&
report errors as follows, unless otherwise specified:
— When a call by the implementation to an operating system or other underlying
API results in an error that prevents the function from meeting its specifications,
an exception of type system_error
shall be thrown.
— Failure to allocate storage is reported by throwing an exception as described in the C++ standard (C++14 [res.on.exception.handling]).
— Destructors throw nothing.
Functions having an argument of type error_code&
report errors as follows, unless otherwise
specified:
— If a call by the implementation to an operating system or other underlying
API results in an error that prevents the function from meeting its specifications,
the error_code&
argument is set as appropriate for the specific error. Otherwise, clear()
is called on the error_code&
argument.
Where a function is specified as two overloads, with and without an argument
of type error_code&
:
R f(A1 a1, A2 a2, ..., AN aN); R f(A1 a1, A2 a2, ..., AN aN, error_code& ec);
then, when R is non-void
, the effects of the first overload
shall be as if:
error_code ec; R r(f(a1, a2, ..., aN, ec)); if (ec) throw system_error(ec, __func__); return r;
Otherwise, when R
is void
, the effects of the
first overload shall be as if:
error_code ec; f(a1, a2, ..., aN, ec); if (ec) throw system_error(ec, __func__);
Asynchronous network library functions are identified by having the prefix
async_
. These asynchronous
operations report errors as follows:
— If a call by the implementation to an operating system or other underlying
API results in an error that prevents the asynchronous operation from meeting
its specifications, the handler shall be invoked with an error_code
value ec
that is set as appropriate for the specific error. Otherwise, the error_code
value ec
is set such that !ec
is true.
— Asynchronous operations shall not fail with an error condition that indicates
interruption by a signal [Note: Such as POSIX
EINTR
—end note]
. Asynchronous operations shall not fail with any error condition associated
with non-blocking operations [Note: Such as POSIX
EWOULDBLOCK
, EAGAIN
or EINPROGRESS
;
Windows WSAEWOULDBLOCK
or WSAEINPROGRESS
—end
note] .
Unless otherwise specified, when the behavior of a synchronous or asynchronous
operation is defined "as if" implemented by a POSIX
function, the error_code
produced by the function shall meet the following requirements:
— If the failure condition is one that is listed by POSIX
for that function, the error_code
shall compare equal to the error's corresponding enum
class errc
(C++14 [syserr]) or enum class resolver_errc
constant.
— Otherwise, the error_code
shall be set to an implementation-defined value that reflects the underlying
operating system error.
[Example: The POSIX specification
for shutdown()
lists EBADF
as one of its
possible errors. If a function that is specified "as if" implemented
by shutdown()
fails with EBADF
then the
following condition holds for the error_code
value ec
: ec == errc::bad_file_descriptor
—end example]
When the description of a function contains the element Error
conditions, this lists conditions where the operation may fail.
The conditions are listed, together with a suitable explanation, as enum class
constants. Unless otherwise specified, this list is a subset of the failure
conditions associated with the function.
#include <experimental/executor> #include <experimental/io_service> #include <experimental/timer> #include <experimental/buffer> #include <experimental/socket> #include <experimental/internet>
[Note: This header is provided as a convenience for
programs so that they may access all networking facilities via a single,
self-contained #include
.
—end note]
namespace std { namespace experimental { inline namespace network_v1 { class execution_context; template<class T, class Executor> class executor_wrapper; template<class T, class Executor> class executor_work; class system_executor; class executor; template<class Executor> class strand; class io_service; template<class Clock> struct wait_traits; template<class Clock, class WaitTraits = wait_traits<Clock>> class basic_waitable_timer; typedef basic_waitable_timer<chrono::system_clock> system_timer; typedef basic_waitable_timer<chrono::steady_clock> steady_timer; typedef basic_waitable_timer<chrono::high_resolution_clock> high_resolution_timer; template<class Protocol> class basic_socket; template<class Protocol> class basic_datagram_socket; template<class Protocol> class basic_stream_socket; template<class Protocol> class basic_socket_acceptor; template<class Protocol, class Clock = chrono::steady_clock, class WaitTraits = wait_traits<Clock>> class basic_socket_streambuf; template<class Protocol, class Clock = chrono::steady_clock, class WaitTraits = wait_traits<Clock>> class basic_socket_iostream; namespace ip { class address; class address_v4; class address_v6; class address_iterator_v4; class address_iterator_v6; class address_range_v4; class address_range_v6; class network_v4; class network_v6; template<class InternetProtocol> class basic_endpoint; template<class InternetProtocol> basic_resolver_query; template<class InternetProtocol> basic_resolver_entry; template<class InternetProtocol> basic_resolver_iterator; template<class InternetProtocol> basic_resolver; class tcp; class udp; } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
Default template arguments are described as appearing both in <netfwd>
and in the synopsis of other headers
but it is well-formed to include both <netfwd>
and one or more of the other headers. [Note: It is
the implementation’s responsibility to implement headers so that including
<netfwd>
and other headers does not violate
the rules about multiple occurrences of default arguments. —end
note]
namespace std { namespace experimental { inline namespace network_v1 { template<class CompletionToken, class Signature, class = void> struct handler_type; template<class CompletionToken, class Signature> using handler_type_t = typename handler_type<CompletionToken, Signature>::type; template<class Handler> class async_result; template<class CompletionToken, class Signature> struct async_completion; template<class T, class Alloc = allocator<void>> struct associated_allocator; template<class T, class Alloc = allocator<void>> using associated_allocator_t = typename associated_allocator<T, Alloc>::type; // get_associated_allocator: template<class T> associated_allocator_t<T> get_associated_allocator(const T& t); template<class T, class Alloc> associated_allocator_t<T, Alloc> get_associated_allocator(const T& t, const Alloc& a); enum class fork_event { prepare, parent, child }; class execution_context; class service_already_exists; template<class Service> Service& use_service(execution_context& ctx); template<class Service, class... Args> Service& make_service(execution_context& ctx, Args&&... args); template<class Service> bool has_service(execution_context& ctx) noexcept; template<class T> struct is_executor : false_type {}; struct executor_arg_t { }; constexpr executor_arg_t executor_arg = executor_arg_t(); template<class T, class Executor> struct uses_executor; template<class T, class Executor = system_executor> struct associated_executor; template<class T, class Executor = system_executor> using associated_executor_t = typename associated_executor<T, Executor>::type; // get_associated_executor: template<class T> associated_executor_t<T> get_associated_executor(const T& t); template<class T, class Executor> associated_executor_t<T, Executor> get_associated_executor(const T& t, const Executor& ex); template<class T, class ExecutionContext> associated_executor_t<T, typename ExecutionContext::executor_type> get_associated_executor(const T& t, ExecutionContext& ctx); template<class T, class Executor> class executor_wrapper; template<class T, class Executor, class Signature> struct handler_type<executor_wrapper<T, Executor>, Signature>; template<class T, class Executor> class async_result<executor_wrapper<T, Executor>>; template<class T, class Executor, class Allocator> struct associated_allocator<executor_wrapper<T, Executor>, Allocator>; template<class T, class Executor, class Executor1> struct associated_executor<executor_wrapper<T, Executor>, Executor1>; // wrap: template<class Executor, class T> executor_wrapper<decay_t<T>, Executor> wrap(const Executor& ex, T&& t); template<class ExecutionContext, class T> executor_wrapper<decay_t<T>, typename ExecutionContext::executor_type> wrap(ExecutionContext& ctx, T&& t); template<class T, class Executor> class executor_work; // make_work: template<class Executor> executor_work<Executor> make_work(const Executor& ex); template<class ExecutionContext> executor_work<typename ExecutionContext::executor_type> make_work(ExecutionContext& ctx); template<class T> executor_work<associated_executor_t<T>> make_work(const T& t); template<class T, class Executor> executor_work<associated_executor_t<T, Executor>> make_work(const T& t, const Executor& ex); template<class T, class ExecutionContext> executor_work<associated_executor_t<T, typename ExecutionContext::executor_type>> make_work(const T& t, ExecutionContext& ctx); class system_executor; bool operator==(const system_executor&, const system_executor&); bool operator!=(const system_executor&, const system_executor&); template<> struct is_executor<system_executor> : true_type {}; class bad_executor; class executor; template <> struct is_executor<executor> : true_type {}; bool operator==(const executor& a, const executor& b) noexcept; bool operator==(const executor& e, nullptr_t) noexcept; bool operator==(nullptr_t, const executor& e) noexcept; bool operator!=(const executor& a, const executor& b) noexcept; bool operator!=(const executor& e, nullptr_t) noexcept; bool operator!=(nullptr_t, const executor& e) noexcept; // dispatch: template<class CompletionToken> auto dispatch(CompletionToken&& token); template<class Executor, class CompletionToken> auto dispatch(const Executor& ex, CompletionToken&& token); template<class ExecutionContext, class CompletionToken> auto dispatch(ExecutionContext& ctx, CompletionToken&& token); // post: template<class CompletionToken> auto post(CompletionToken&& token); template<class Executor, class CompletionToken> auto post(const Executor& ex, CompletionToken&& token); template<class ExecutionContext, class CompletionToken> auto post(ExecutionContext& ctx, CompletionToken&& token); // defer: template<class CompletionToken> auto defer(CompletionToken&& token); template<class Executor, class CompletionToken> auto defer(const Executor& ex, CompletionToken&& token); template<class ExecutionContext, class CompletionToken> auto defer(ExecutionContext& ctx, CompletionToken&& token); template<class Executor> class strand; template<class Executor> bool operator==(const strand<Executor>& a, const strand<Executor>& b); template<class Executor> bool operator!=(const strand<Executor>& a, const strand<Executor>& b); template<class Executor> struct is_executor<strand<Executor>> : true_type {}; template<class Allocator = allocator<void>> class use_future_t; constexpr use_future_t<> use_future = use_future_t<>(); template<class Allocator, class R, class... Args> struct handler_type<use_future_t<Allocator>, R(Args...)>; template<class R, class... Args> class async_result<packaged_task<R(Args...)>>; template<class Signature, class Alloc> class packaged_handler; template<class Signature, class Alloc> class async_result<packaged_handler<Signature, Alloc>>; template<class Func, class Alloc = allocator<void>> class packaged_token; template<class Func, class Alloc, class R, class... Args> struct handler_type<packaged_token<Func, Alloc>, R(Args...)>; template<class Func, class Alloc = allocator<void>> packaged_token<decay_t<Func>, Alloc> package(Func&& f, const Alloc& a = Alloc()); } // inline namespace network_v1 } // namespace experimental template<class Alloc> struct uses_allocator<std::experimental::network_v1::executor, Alloc> : true_type {}; } // namespace std
In this clause, an asynchronous operation is initiated by a function
that is named with the prefix async_
.
These functions shall be known as initiating functions.
All initiating functions in this clause:
— are function templates with template parameter CompletionToken
;
— accept, as the final parameter, a completion token
object token
of type
CompletionToken
;
— specify a Completion signature element that defines
a call signature Signature
.
A handler is a function object that will be invoked, at most once, with the result of an asynchronous operation.
An initiating function determines the type Handler
of its handler function object by performing handler_type_t<CompletionToken, Signature>
. The handler object handler
is initialized with handler(forward<CompletionToken>(token))
.
The type Handler
must
satisfy the MoveConstructible
requirements (C++ Std, [moveconstructible]) and be callable with the
specified completion signature. The Completion signature
elements in this clause have named parameters, and the result of an
asynchronous operation is specified in terms of these names.
All initiating functions in this clause are specified using automatic
return type deduction. The function return type shall be determined
as if by typename async_result<Handler>::type
.
All initiating functions in this clause produce their return type as follows:
— constructing an object result
of type async_result<Handler>
, initializing the object as result(handler)
;
and
— using result.get()
as the return expression.
[Example: Given an asynchronous operation with
Completion signature void(R1 r1, R2 r2)
, an initiating function meeting these
requirements may be implemented as follows:
template<class CompletionToken> auto async_xyz(T1 t1, T2 t2, CompletionToken&& token) { handler_type_t<CompletionToken, void(R1 r1, R2 r2)> handler(forward<CompletionToken>(token)); async_result<decltype(handler)> result(handler); // initiate the operation and cause handler to be invoked with the result return result.get(); }
For convenience, initiating functions may be implemented using the
async_completion
template:
template<class CompletionToken> auto async_xyz(T1 t1, T2 t2, CompletionToken&& token) { async_completion<CompletionToken, void(R1 r1, R2 r2)> init(token); // initiate the operation and cause init.handler to be invoked with the result return init.result.get(); }
—end example]
Unless otherwise specified, the lifetime of arguments to initiating functions shall be treated as follows:
— If the parameter is declared as a const reference, rvalue reference, or by-value, the implementation must not assume the validity of the argument after the initiating function completes. [Note: In other words, the program is not required to guarantee the validity of the argument after the initiating function completes. —end note] The implementation may make copies of the argument, and all copies shall be destroyed no later than immediately after invocation of the handler.
— If the parameter is declared as a non-const reference, const pointer or non-const pointer, the implementation may assume the validity of the argument until the handler is invoked. [Note: In other words, the program must guarantee the validity of the argument until the handler is invoked. —end note]
All asynchronous operations in this clause have an associated executor
object satisfying Executor requirements.
Where the initiating function is a member function, the associated
executor is that returned by the get_executor
member function on the same object. Where the initiating function is
not a member function, the associated executor is that returned by
the get_executor
member
function of the first argument to the initiating function. Let Executor1
be the type of the associated
executor, and ex1
be
the associated executor object obtained as described above.
All handler objects have an associated executor object satisfying
Executor requirements.
The type Executor2
of the handler's associated executor shall be determined by associated_executor_t<Handler,
Executor1>
.
The handler's associated executor object ex2
shall be obtained by performing associated_executor<Handler, Executor1>::get(handler, ex1)
.
The implementation of an asynchronous operation shall maintain an object
work1
of type executor_work<Executor1>
,
initialized with work1(ex1)
and with work1.owns_work() == true
, until the effects of the asynchronous
operation have been realized.
The implementation of an asynchronous operation shall maintain an object
work2
of type executor_work<Executor2>
,
initialized with work2(ex2)
and with work2.owns_work() == true
, until handler
has been submitted for execution.
Asynchronous operations may allocate memory. [Note:
Such as a data structure to store copies of the handler
object and the initiating function's arguments. —end note]
Let Alloc1
be a type,
satisfying Allocator
requirements (C++ Std, [allocator.requirements]), that represents the
asynchronous operation's default allocation strategy. [Note:
Typically std::allocator<void>
.
—end note] Let alloc1
be an object of type Alloc1
.
All handlers have an associated allocator object satisfying Allocator
requirements. The type
Alloc2
of the handler's
associated allocator shall be determined by associated_allocator_t<Handler, Alloc1>
. The handler's associated allocator
object alloc2
shall
be obtained by performing associated_allocator<Handler, Executor1>::get(handler, alloc1)
.
The asynchronous operations defined in this clause:
— May allocate memory using the handler's associated allocator.
— Shall deallocate all memory allocated using the handler's associated allocator prior to handler execution.
— Shall ensure that calls to the handler's associated allocator, or to copies of the handler's associated allocator, are not performed concurrently in a way that would introduce a data race.
When an asynchronous operation completes, the implementation constructs
a zero-argument function object bound_handler
to invoke handler
with
results of the operation.
If an asynchonous operation completes immediately (that is, within
the thread calling the initiating function, and before the initiating
function returns), the handler shall be submitted for execution as
if by performing ex2.post(bound_handler, alloc2)
. Otherwise, the handler shall be submitted
for execution as if by performing ex2.dispatch(bound_handler, alloc2)
.
The library describes a standard set of requirements for executors. A type meeting Executor requirements shall embody a set of rules for determining how submitted function objects are to be executed.
An executor type X
shall
satisfy the requirements of CopyConstructible
(C++ Std, [copyconstructible]) types. No constructor, comparison operator,
copy operation, move operation, swap operation, or member functions
context
, on_work_started
and on_work_finished
on these types shall exit via an exception.
The executor copy constructor, comparison operators, and member functions defined in these requirements shall not introduce data races as a result of concurrent calls to those functions from different threads.
In the table below, X
denotes an executor class, x
denotes a value of type X&
, x1
and x2
denote values
of type const X&
, x3
denotes a value of type X&&
, f
denotes a MoveConstructible
(C++ Std, [moveconstructible]) function object callable with zero arguments,
a
denotes a value of
type A
meeting Allocator
requirements (C++ Std, [allocator.requirements]),
t
denotes an object of
type T
, and u
denotes an identifier.
Table 3. Executor requirements
expression |
type |
assertion/note |
---|---|---|
|
Shall not exit via an exception. | |
|
Shall not exit via an exception. | |
|
|
Shall not exit via an exception. |
|
|
Shall not exit via an exception. |
|
|
Shall not exit via an exception. |
|
Shall not exit via an exception. | |
|
Shall not exit via an exception. | |
|
Effects: Calls | |
|
Effects: Calls | |
|
Effects: Calls |
A class is a service if it is publicly derived from another service,
or if it is a class publicly derived from execution_context::service
.
A service may contain a publicly-accessible nested typedef named key_type
. If the nested typedef key_type
exists, the service class
shall be the same type as key_type
,
or otherwise publicly and unambiguously derived from key_type
.
All services define a one-argument constructor that takes a reference
to the execution_context
object that owns the service. This constructor is explicit,
preventing its participation in automatic conversions.
A service may provide additional constructors with two or more arguments,
where the first argument is a reference to the execution_context
object that owns the service. [Note: These constructors
may be called by the make_service
function. —end note]
[Example:
class my_service : public execution_context::service { public: typedef my_service key_type; explicit my_service(execution_context& ctx); private: virtual void shutdown_service(); ... };
—end example]
A service's shutdown_service
member function must cause all copies of user-defined function objects
that are held by the service to be destroyed.
namespace std { namespace experimental { inline namespace network_v1 { template<class CompletionToken, class Signature, class = void> struct handler_type { typedef see below type; }; } // inline namespace network_v1 } // namespace experimental } // namespace std
Template parameter CompletionToken
specifies the model used to obtain the result of the asynchronous operation.
Template parameter Signature
is the call signature (C++ Std, [func.def]) for the handler type invoked
on completion of the asynchronous operation.
A program may specialize this trait if the CompletionToken
template parameter in the specialization is a user-defined type.
Specializations of handler_type
shall define a nested handler type type
that satisfies the MoveConstructible
requirements, and objects of type type
shall be constructible from an lvalue or rvalue of the type specified by
the CompletionToken
template
parameter.
namespace std { namespace experimental { inline namespace network_v1 { template<class Handler> class async_result { public: typedef void type; explicit async_result(Handler&); async_result(const async_result&) = delete; async_result& operator=(const async_result&) = delete; type get(); }; } // inline namespace network_v1 } // namespace experimental } // namespace std
Template argument Handler
is a handler type produced by handler_type_t<T, S>
for some completion token type T
and call signature S
.
A program may specialize this template if the Handler
template parameter in the specialization is a user-defined type.
Specializations of async_result
shall satisfy the Destructible
requirements (C++ Std, [destructible]) in addition to the requirements
in the table below. In this table, R
is a specialization of async_result
for the template parameter Handler
;
r
is a modifiable lvalue
of type R
; and h
is a modifiable lvalue of type Handler
.
Table 4. async_result specialization requirements
Expression |
Return type |
Note |
---|---|---|
|
| |
| ||
|
|
The |
namespace std { namespace experimental { inline namespace network_v1 { template<class CompletionToken, class Signature> struct async_completion { typedef handler_type_t<CompletionToken, Signature> handler_type; explicit async_completion(remove_reference_t<CompletionToken>& t); async_completion(const async_completion&) = delete; async_completion& operator=(const async_completion&) = delete; see below handler; async_result<handler_type> result; }; } // inline namespace network_v1 } // namespace experimental } // namespace std
Template parameter CompletionToken
specifies the model used to obtain the result of the asynchronous operation.
Template parameter Signature
is the call signature (C++ Std, [func.def]) for the handler type invoked
on completion of the asynchronous operation.
explicit async_completion(remove_reference_t<CompletionToken>& t);
Effects: If
CompletionToken
andhandler_type
are the same type, bindshandler
tot
; otherwise, initializeshandler
with the result offorward<CompletionToken>(t)
. Initializesresult
withhandler
.
see below handler;
Type:
handler_type&
ifCompletionToken
andhandler_type
are the same type; otherwise,handler_type
.
namespace std { namespace experimental { inline namespace network_v1 { template<class T, class Alloc = allocator<void>> struct associated_allocator { typedef see below type; static type get(const T& t, const Alloc& a = Alloc()) noexcept; }; } // inline namespace network_v1 } // namespace experimental } // namespace std
A program may specialize this traits type if the T
template parameter in the specialization is a user-defined type. The template
parameter Alloc
shall be
a type meeting Allocator
requirements (C++ Std, [allocator.requirements]).
Specializations of associated_allocator
shall satisfy the requirements in the table below. In this table, X
is a specialization of associated_allocator
for the template
parameter T
; t
is a const reference to an object of
type T
; and a
is an object of type Alloc
.
Table 5. associated_allocator specialization requirements
Expression |
Return type |
Note |
---|---|---|
|
A type meeting | |
|
|
Shall not exit via an exception. |
|
|
Shall not exit via an exception. |
template<class T> associated_allocator_t<T> get_associated_allocator(const T& t);
Returns:
associated_allocator<T>::get(t)
.
template<class T, class Alloc> associated_allocator_t<T, Alloc> get_associated_allocator(const T& t, const Alloc& a);
Returns:
associated_allocator<T, Alloc>::get(t, a)
.
namespace std { namespace experimental { inline namespace network_v1 { class execution_context { public: class service; // construct / copy / destroy: execution_context(); execution_context(const execution_context&) = delete; execution_context& operator=(const execution_context&) = delete; virtual ~execution_context(); // execution context operations: void notify_fork(fork_event e); protected: // execution context protected operations: void shutdown_context(); void destroy_context(); }; // service access: template<class Service> Service& use_service(execution_context& ctx); template<class Service, class... Args> Service& make_service(execution_context& ctx, Args&&... args); template<class Service> bool has_service(execution_context& ctx) noexcept; class service_already_exists : public logic_error { ... }; } // inline namespace network_v1 } // namespace experimental } // namespace std
Class execution_context
implements an extensible, type-safe, polymorphic set of services, indexed
by service type.
Access to the services of an execution_context
is via three function templates, use_service<>
, make_service<>
and has_service<>
.
In a call to use_service<Service>()
, the type argument chooses a service,
making available all members of the named type. If the service is not present
in an execution_context
,
an object of type Service
is created and added to the execution_context
.
A C++ program can check if an execution_context
implements a particular service with the function template has_service<Service>()
.
Service objects may be explicitly added to an execution_context
using the function template make_service<Service>()
. If the service is already present,
the service_already_exists
exception is thrown.
Once a service reference is obtained from an execution_context
object by calling use_service<>
, that reference remains usable
until a call to destroy_context()
.
execution_context();
Effects: Creates an object of class
execution_context
.
~execution_context();
Effects: Destroys an object of class
execution_context
. Performsshutdown_context()
followed bydestroy_context()
.
void notify_fork(fork_event e);
Effects: For each service object
svc
in the set:
— Ife == fork_event::prepare
, performssvc->notify_fork(e)
in reverse order of the beginning of service object lifetime (C++ Std, [basic.life]).
— Otherwise, performssvc->notify_fork(e)
in order of the beginning of service object lifetime.
void shutdown_context();
Effects: For each service object
svc
in theexecution_context
set, in reverse order of the beginning of service object lifetime (C++ Std, [basic.life]), performssvc->shutdown_service()
.
[Note:
shutdown_context
is an idempotent operation. —end note]
void destroy_context();
Effects: Destroys each service object in the
execution_context
set, in reverse order of the beginning of service object lifetime (C++ Std, [basic.life]).
[Note:
destroy_context
is an idempotent operation. —end note]
The functions use_service
,
make_service
and has_service
shall not introduce data
races as a result of concurrent calls to those functions from different
threads.
template<class Service> Service& use_service(execution_context& ctx);
Let
Key
beService::key_type
if the nested typedefService::key_type
exists; otherwise, letKey
beService
.
Requires:
Service
is a service class that is publicly and unambiguously derived fromexecution_context::service
. If the nested typedefService::key_type
exists,Service
is the same type asService::key_type
, orService
is publicly and unambiguously derived fromService::key_type
, andService::key_type
is publicly and unambiguously derived fromexecution_context::service
.
Effects: If an object of type
Key
does not already exist in theexecution_context
set identified byctx
, creates an object of typeService
, initializing it withService(ctx)
, and adds it to the set.
Returns: A reference to the corresponding service of
ctx
.
Notes: The reference returned remains valid until a call to
destroy_context
.
template<class Service, class... Args> Service& make_service(execution_context& ctx, Args&&... args);
Let
Key
beService::key_type
if the nested typedefService::key_type
exists; otherwise, letKey
beService
.
Requires:
Service
is a service class that is publicly and unambiguously derived fromexecution_context::service
. If the nested typedefService::key_type
exists,Service
is the same type asService::key_type
, orService
is publicly and unambiguously derived fromService::key_type
, andService::key_type
is publicly and unambiguously derived fromexecution_context::service
. A service object of typeKey
does not already exist in theexecution_context
set identified byctx
.
Effects: Creates an object of type
Service
, initializing it withService(ctx, forward<Args>(args)...)
, and adds it to theexecution_context
set identified byctx
.
Throws:
service_already_exists
if a corresponding service object of typeKey
is already present in the set.
Notes: The reference returned remains valid until a call to
destroy_context
.
template<class Service> bool has_service(execution_context& ctx) noexcept;
Let
Key
beService::key_type
if the nested typedefService::key_type
exists; otherwise, letKey
beService
.
Requires:
Service
is a service class that is publicly and unambiguously derived fromexecution_context::service
. If the nested typedefService::key_type
exists,Service
is the same type asService::key_type
, orService
is publicly and unambiguously derived fromService::key_type
, andService::key_type
is publicly and unambiguously derived fromexecution_context::service
.
Returns: If an object of type
Key
is present inctx
,true
; otherwise,false
.
namespace std { namespace experimental { inline namespace network_v1 { class execution_context::service { protected: // construct / copy / destroy: service(execution_context& owner); service(const service&) = delete; service& operator=(const service&) = delete; virtual ~service(); // service observers: execution_context& context() noexcept; private: friend class execution_context; // exposition only // service operations: virtual void shutdown_service() = 0; virtual void notify_fork(fork_event e); execution_context& context_; // exposition only }; } // inline namespace network_v1 } // namespace experimental } // namespace std
service(execution_context& owner);
Postconditions:
&context_ == &owner
.
execution_context& context() noexcept;
Returns:
context_
.
namespace std { namespace experimental { inline namespace network_v1 { template<class T> struct is_executor : false_type {}; } // inline namespace network_v1 } // namespace experimental } // namespace std
is_executor
can be used
to detect executor types satisfying the Executor
type requirements.
Instantiations of the is_executor
template shall meet the UnaryTypeTrait requirements (C++ Std, [meta.rqmts]).
A program may specialize this template for a user-defined type T
to have a BaseCharacteristic of integral_constant<int,
N
>
with N
> 0
to indicate that T
should be treated as an executor type.
namespace std { namespace experimental { inline namespace network_v1 { struct executor_arg_t { }; constexpr executor_arg_t executor_arg = executor_arg_t(); } // inline namespace network_v1 } // namespace experimental } // namespace std
The executor_arg_t
struct
is an empty structure type used as a unique type to disambiguate constructor
and function overloading. Specifically, types may have constructors with
executor_arg_t
as the first
argument, immediately followed by an argument of a type that satisfies
the Executor requirements.
namespace std { namespace experimental { inline namespace network_v1 { template<class T, class Executor> struct uses_executor; } // inline namespace network_v1 } // namespace experimental } // namespace std
Remark: Detects whether T
has a nested executor_type
that is convertible from Executor
.
Meets the BinaryTypeTrait
requirements (C++ Std, [meta.rqmts]). The implementation shall provide
a definition that is derived from false_type
.
A program may specialize this template to derive from true_type
for a user-defined type T
that does not have a nested executor_type
but nonetheless can be constructed with an executor where either:
— the first argument of a constructor has type executor_type
and the second argument has type Executor
;
or
— the last argument of a constructor has type Executor
.
Uses-executor construction with executor Executor
refers to the construction
of an object obj
of type
T
, using constructor
arguments v1,
v2,
..., vN
of types V1,
V2,
..., VN
,
respectively, and an executor ex
of type Executor
, according
to the following rules:
— if uses_executor<T, Executor>::value
is false and is_constructible<T, V1, V2, ..., VN>::value
is true, then obj
is initialized as obj(v1, v2, ..., vN)
;
— otherwise, if uses_executor<T, Executor>::value
is true and is_constructible<T, executor_arg_t, Executor, V1, V2, ..., VN>::value
is true, then obj
is initialized as obj(executor_arg, ex, v1, v2, ..., vN)
;
— otherwise, if uses_executor<T, Executor>::value
is true and is_constructible<T, V1, V2, ..., VN, Executor>::value
is true, then obj
is initialized as obj(v1, v2, ..., vN, ex)
;
— otherwise, the request for uses-executor construction is ill-formed.
[Note: An error will result if uses_executor<T, Executor>::value
is true but the specific constructor does not take an executor. This
definition prevents a silent failure to pass the executor to an element.
—end note]
namespace std { namespace experimental { inline namespace network_v1 { template<class T, class Executor = system_executor> struct associated_executor { typedef see below type; static type get(const T& t, const Executor& e = Executor()) noexcept; }; } // inline namespace network_v1 } // namespace experimental } // namespace std
A program may specialize this traits type if the T
template parameter in the specialization is a user-defined type. The template
parameter Executor
shall
be a type meeting Executor requirements.
Specializations of associated_executor
shall satisfy the requirements in the table below. In this table, X
is a specialization of associated_executor
for the template
parameter T
; t
is a const reference to an object of
type T
; and e
is an object of type Executor
.
Table 6. associated_executor specialization requirements
Expression |
Return type |
Note |
---|---|---|
|
A type meeting Executor requirements. | |
|
|
Shall not exit via an exception. |
|
|
Shall not exit via an exception. |
template<class T> associated_executor_t<T> get_associated_executor(const T& t);
Returns:
associated_executor<T>::get(t)
.
template<class T, class Executor> associated_executor_t<T, Executor> get_associated_executor(const T& t, const Executor& ex);
Returns:
associated_executor<T, Executor>::get(t, ex)
.
Remarks: This function shall not participate in overload resolution unless
is_executor<Executor>::value
is true.
template<class T, class ExecutionContext> associated_executor_t<T, typename ExecutionContext::executor_type> get_associated_executor(const T& t, ExecutionContext& ctx);
Returns:
associated_executor<T, typename ExecutionContext::executor_type>::get(t, ctx.get_executor())
.
Remarks: This function shall not participate in overload resolution unless
is_convertible<ExecutionContext&, execution_context&>::value
is true.
namespace std { namespace experimental { inline namespace network_v1 { template<class T, class Executor> class executor_wrapper { public: // types: typedef T wrapped_type; typedef Executor executor_type; typedef see below result_type; // not always defined typedef see below argument_type; // not always defined typedef see below first_argument_type; // not always defined typedef see below second_argument_type; // not always defined // construct / copy / destroy: executor_wrapper(T t, const Executor& ex); executor_wrapper(const executor_wrapper& other) = default; executor_wrapper(executor_wrapper&& other) = default; template<class U, class OtherExecutor> executor_wrapper(const executor_wrapper<U, OtherExecutor>& other); template<class U, class OtherExecutor> executor_wrapper(executor_wrapper<U, OtherExecutor>&& other); template<class U, class OtherExecutor> executor_wrapper(executor_arg_t, const Executor& ex, const executor_wrapper<U, OtherExecutor>& other); template<class U, class OtherExecutor> executor_wrapper(executor_arg_t, const Executor& ex, executor_wrapper<U, OtherExecutor>&& other); ~executor_wrapper(); // executor wrapper access: T& unwrap() noexcept; const T& unwrap() const noexcept; executor_type get_executor() const noexcept; // executor wrapper invocation: template<class... Args> result_of_t<cv T&(Args&&...)> operator()(Args&&... args) cv; private: Executor ex_; // exposition only T wrapped_; // exposition only }; template<class T, class Executor, class Signature> struct handler_type<executor_wrapper<T, Executor>, Signature> { typedef executor_wrapper<handler_type_t<T, Signature>, Executor> type; }; template<class T, class Executor> class async_result<executor_wrapper<T, Executor>>; template<class T, class Executor, class Alloc> struct associated_allocator<executor_wrapper<T, Executor>, Alloc>; template<class T, class Executor, class Executor1> struct associated_executor<executor_wrapper<T, Executor>, Executor1>; } // inline namespace network_v1 } // namespace experimental } // namespace std
executor_wrapper<T, Executor>
is a wrapper around an object or function
of type T
, and an executor
object of type Executor
satisfying Executor requirements.
executor_wrapper<T, Executor>
has a weak result type (C++ Std, [func.require]).
If T
is a function type,
result_type
shall be a
synonym for the return type of T
.
The template instantiation executor_wrapper<T, Executor>
shall define a nested type named argument_type
as a synonym for T1
only if the type T
is any of the following:
— a function type or a pointer to function type taking one argument of type
T1
— a pointer to member function R
T0::f
cv
(where cv
represents the member
function’s cv-qualifiers); the type T1
is cv
T0*
— a class type with a member type argument_type
;
the type T1
is T::argument_type
.
The template instantiation executor_wrapper<T, Executor>
shall define two nested types named
first_argument_type
and
second_argument_type
as
synonyms for T1
and T2
, respectively, only if the type T
is any of the following:
— a function type or a pointer to function type taking two arguments of types
T1
and T2
— a pointer to member function R
T0::f(T2)
cv
(where cv
represents the member
function’s cv-qualifiers); the type T1
is cv
T0*
— a class type with member types first_argument_type
and second_argument_type
;
the type T1
is T::first_argument_type
.
and the type T2
is T::second_argument_type
.
executor_wrapper(T t, const Executor& ex);
Effects: Constructs an object of type
executor_wrapper<T, Executor>
. Initializesex_
with the valueex
. Ifuses_executor<T, Executor>::value
is true, performs uses-executor construction to initializewrapped_
withwrapped_(executor_arg, ex_, std::move(t))
; otherwise, initializeswrapped_
withwrapped_(std::move(t))
.
template<class U, class OtherExecutor> executor_wrapper(const executor_wrapper<U, OtherExecutor>& other);
Requires:
U
isT
or convertible toT
.OtherExecutor
isExecutor
or convertible toExecutor
.
Effects: Constructs an object of type
executor_wrapper<T, Executor>
. Initializesex_
withother.get_executor()
. Ifuses_executor<T, Executor>::value
is true, performs uses-executor construction to initializewrapped_
withwrapped_(executor_arg, ex_, other.unwrap())
; otherwise, initializeswrapped_
withwrapped_(other.unwrap())
.
template<class U, class OtherExecutor> executor_wrapper(executor_wrapper<U, OtherExecutor>&& other);
Requires:
U
isT
or convertible toT
.OtherExecutor
isExecutor
or convertible toExecutor
.
Effects: Constructs an object of type
executor_wrapper<T, Executor>
. Initializesex_
withother.get_executor()
. Ifuses_executor<T, Executor>::value
is true, performs uses-executor construction to initializewrapped_
withwrapped_(executor_arg, ex_, std::move(other.unwrap()))
; otherwise, initializeswrapped_
withwrapped_(std::move(other.unwrap()))
.
template<class U, class OtherExecutor> executor_wrapper(executor_arg_t, const Executor& ex, const executor_wrapper<U, OtherExecutor>& other);
Requires:
U
isT
or convertible toT
.
Effects: Constructs an object of type
executor_wrapper<T, Executor>
. Initializesex_
withex
. Ifuses_executor<T, Executor>::value
is true, performs uses-executor construction to initializewrapped_
withwrapped_(executor_arg, ex_, other.unwrap())
; otherwise, initializeswrapped_
withwrapped_(other.unwrap())
.
template<class U, class OtherExecutor> executor_wrapper(executor_arg_t, const Executor& ex, executor_wrapper<U, OtherExecutor>&& other);
Requires:
U
isT
or convertible toT
.
Effects: Constructs an object of type
executor_wrapper<T, Executor>
. Initializesex_
withex
. Ifuses_executor<T, Executor>::value
is true, performs uses-executor construction to initializewrapped_
withwrapped_(executor_arg, ex_, std::move(other.unwrap()))
; otherwise, initializeswrapped_
withwrapped_(std::move(other.unwrap()))
.
T& unwrap() noexcept; const T& unwrap() const noexcept;
Returns:
wrapped_
.
executor_type get_executor() const noexcept;
Returns:
executor_
.
template<class... Args> result_of_t<cv T&(Args&&...)> operator()(Args&&... args) cv;
Returns:
INVOKE
(unwrap(), forward<Args>(args)...)
(C++ Std, [func.require]).
Remarks:
operator()
is described for exposition only. Implementations are not required to provide an actualexecutor_wrapper::operator()
. Implementations are permitted to supportexecutor_wrapper
function invocation through multiple overloaded operators or through other means.
namespace std { namespace experimental { inline namespace network_v1 { template<class T, class Executor> class async_result<executor_wrapper<T, Executor>> { public: typedef typename async_result<T>::type type; explicit async_result(executor_wrapper<T, Executor>& wrapper); async_result(const async_result&) = delete; async_result& operator=(const async_result&) = delete; type get(); private: async_result<T> wrapped_; // exposition only }; } // inline namespace network_v1 } // namespace experimental } // namespace std
The implementation shall provide a specialization of async_result
that meets the async_result
specialization requirements.
explicit async_result(executor_wrapper<T, Executor>& wrapper);
Effects: Initializes
wrapped_
withwrapped_(wrapper.unwrap())
.
type get();
Returns:
wrapped_.get()
.
namespace std { namespace experimental { inline namespace network_v1 { template<class T, class Executor, class Alloc> struct associated_allocator<executor_wrapper<T, Executor>, Alloc> { typedef associated_allocator_t<T, Alloc> type; static type get(const executor_wrapper<T, Executor>& w, const Alloc& a = Alloc()) noexcept; }; } // inline namespace network_v1 } // namespace experimental } // namespace std
The implementation shall provide a specialization of associated_allocator
that meets the associated_allocator
specialization
requirements.
static type get(const executor_wrapper<T, Executor>& w, const Alloc& a = Alloc()) noexcept;
Returns:
associated_allocator<T, Alloc>::get(w.unwrap(), a)
.
namespace std { namespace experimental { inline namespace network_v1 { template<class T, class Executor, class Executor1> struct associated_executor<executor_wrapper<T, Executor>, Executor1> { typedef Executor type; static type get(const executor_wrapper<T, Executor>& w, const Executor1& e = Executor1()) noexcept; }; } // inline namespace network_v1 } // namespace experimental } // namespace std
The implementation shall provide a specialization of associated_executor
that meets the associated_executor
specialization
requirements.
static type get(const executor_wrapper<T, Executor>& w, const Executor1& e = Executor1()) noexcept;
Returns:
w.get_executor()
.
template<class Executor, class T> executor_wrapper<decay_t<T>, Executor> wrap(const Executor& ex, T&& t);
Returns:
executor_wrapper<decay_t<T>, Executor>(forward<T>(t), ex)
.
Remarks: This function shall not participate in overload resolution unless
is_executor<Executor>::value
is true.
template<class ExecutionContext, class CompletionToken> executor_wrapper<decay_t<T>, typename ExecutionContext::executor_type> wrap(ExecutionContext& ctx, T&& t);
Returns:
executor_wrapper<decay_t<T>, typename ExecutionContext::executor_type>(forward<T>(t), ctx.get_executor())
.
Remarks: This function shall not participate in overload resolution unless
is_convertible<ExecutionContext&, execution_context&>::value
is true.
namespace std { namespace experimental { inline namespace network_v1 { template<class Executor> class executor_work { public: // types: typedef Executor executor_type; // construct / copy / destroy: explicit executor_work(const executor_type& ex) noexcept; executor_work(const executor_work& other) noexcept; executor_work(executor_work&& other) noexcept; executor_work operator=(const executor_type&) = delete; ~executor_work(); // executor work observers: executor_type get_executor() const noexcept; bool owns_work() const noexcept; // executor work modifiers: void reset() noexcept; private: Executor ex_; // exposition only bool owns_; // exposition only }; } // inline namespace network_v1 } // namespace experimental } // namespace std
explicit executor_work(const executor_type& ex) noexcept;
Effects: Constructs an object of class
executor_work
, initializingex_
withex
, and then performingex_.on_work_started()
.
Postconditions:
ex == ex_
andowns_ == true
.
executor_work(const executor_work& other) noexcept;
Effects: Constructs an object of class
executor_work
, initializingex_
withother.ex
. Ifother.owns_ == true
, performsex_.on_work_started()
.
Postconditions:
ex == other.ex_
andowns_ == other.owns_
.
executor_work(executor_work&& other) noexcept;
Effects: Constructs an object of class
executor_work
, initializingex_
withother.ex
andowns_
withother.owns_
.
Postconditions:
ex
is equal to the prior value ofother.ex_
,owns_
is equal to the prior value ofother.owns_
, andother.owns_ == false
.
executor_type get_executor() const noexcept;
Returns:
ex_
.
bool owns_work() const noexcept;
Returns:
owns_
.
template<class Executor> executor_work<Executor> make_work(const Executor& ex);
Returns:
executor_work<Executor>(ex)
.
Remarks: This function shall not participate in overload resolution unless
is_executor<Executor>::value
is true.
template<class ExecutionContext> executor_work<typename ExecutionContext::executor_type> make_work(ExecutionContext& ctx);
Returns: An object of type
executor_work<typename ExecutionContext::executor_type>
initialized with the result ofctx.get_executor()
.
Remarks: This function shall not participate in overload resolution unless
is_convertible<ExecutionContext&, execution_context&>::value
is true.
template<class T> executor_work<associated_executor_t<T>> make_work(const T& t);
Returns: An object of type
executor_work<associated_executor_t<T>>
initialized with the result ofassociated_executor<T>::get(t)
.
Remarks: This function shall not participate in overload resolution unless
is_executor<T>::value
is false andis_convertible<T&, execution_context&>::value
is false.
template<class T, class Executor> executor_work<associated_executor_t<T, Executor>> make_work(const T& t, const Executor& ex);
Returns: An object of type
executor_work<associated_executor_t<T, Executor>>
initialized with the result ofassociated_executor<T, Executor>::get(t, ex)
.
Remarks: This function shall not participate in overload resolution unless
is_executor<Executor>::value
is true.
template<class T, class ExecutionContext> executor_work<associated_executor_t<T, typename ExecutionContext::executor_type>> make_work(const T& t, ExecutionContext& ctx);
Returns: An object of type
executor_work<associated_executor_t<T, typename ExecutionContext::executor_type>>
initialized with the result ofassociated_executor<T, typename ExecutionContext::executor_type>::get(t, ctx.get_executor())
.
Remarks: This function shall not participate in overload resolution unless
is_convertible<ExecutionContext&, execution_context&>::value
is true.
namespace std { namespace experimental { inline namespace network_v1 { class system_executor { public: // executor operations: execution_context& context() noexcept; void on_work_started() noexcept; void on_work_finished() noexcept; template<class Func, class Alloc> void dispatch(Func&& f, const Alloc& a); template<class Func, class Alloc> void post(Func&& f, const Alloc& a); template<class Func, class Alloc> void defer(Func&& f, const Alloc& a); }; bool operator==(const system_executor&, const system_executor&) noexcept; bool operator!=(const system_executor&, const system_executor&) noexcept; } // inline namespace network_v1 } // namespace experimental } // namespace std
Class system_executor
is
a DefaultConstructible
type (C++ Std, [defaultconstructible]) satisfying Executor
requirements. It represents a set of rules where function objects
are permitted to execute on any thread.
To satisfy the executor requirements for the post
and defer
member functions,
the system executor may allocate thread
objects to run the submitted function objects. If std::exit
is called, and there remain unexecuted functions objects that have been
submitted using post
or
defer
, the implementation
shall discard these function objects without calling them.
execution_context& context() noexcept;
Returns: A reference to a static-duration object of a type derived from
execution_context
.
void on_work_started() noexcept;
Effects: Does nothing.
void on_work_finished() noexcept;
Effects: Does nothing.
template<class Func, class Alloc> void dispatch(Func&& f, const Alloc& a);
Effects: Calls
DECAY_COPY
(forward<Func>(f))()
.
template<class Func, class Alloc> void post(Func&& f, const Alloc& a);
Effects: Calls
DECAY_COPY
(forward<Func>(f))()
as if in a thread of execution represented by athread
object, with the call toDECAY_COPY()
being evaluated in the thread that calledpost
. Any exception propagated from the execution ofDECAY_COPY
(forward<Func>(f))()
shall result in a call tostd::terminate
.
template<class Func, class Alloc> void defer(Func&& f, const Alloc& a);
Effects: Calls
DECAY_COPY
(forward<Func>(f))()
as if in a thread of execution represented by athread
object, with the call toDECAY_COPY()
being evaluated in the thread that calleddefer
. Any exception propagated from the execution ofDECAY_COPY
(forward<Func>(f))()
shall result in a call tostd::terminate
.
namespace std { namespace experimental { inline namespace network_v1 { class bad_executor : public exception { public: // constructor: bad_executor() noexcept; }; } // inline namespace network_v1 } // namespace experimental } // namespace std
An exception of type bad_executor
is thrown by executor
member
functions dispatch
, post
and defer
when the executor object has no target.
namespace std { namespace experimental { inline namespace network_v1 { class executor { public: // construct / copy / destroy: executor() noexcept; executor(nullptr_t) noexcept; executor(const executor& e) noexcept; executor(executor&& e) noexcept; template<class Executor> executor(Executor e); template<class Executor, class Alloc> executor(allocator_arg_t, const Alloc& a, Executor e); executor& operator=(const executor& e) noexcept; executor& operator=(executor&& e) noexcept; executor& operator=(nullptr_t) noexcept; template<class Executor> executor& operator=(Executor e); ~executor(); // executor modifiers: void swap(executor& other) noexcept; template<class Executor, class Alloc> void assign(Executor e, const Alloc& e); // executor operations: execution_context& context() noexcept; void on_work_started() noexcept; void on_work_finished() noexcept; template<class Func, class Alloc> void dispatch(Func&& f, const Alloc& a); template<class Func, class Alloc> void post(Func&& f, const Alloc& a); template<class Func, class Alloc> void defer(Func&& f, const Alloc& a); // executor capacity: explicit operator bool() const noexcept; // executor target access: const type_info& target_type() const noexcept; template<class Executor> Executor* target() noexcept; template<class Executor> const Executor* target() const noexcept; }; template<> struct is_executor<executor> : true_type {}; // executor comparisons: bool operator==(const executor& a, const executor& b) noexcept; bool operator==(const executor& e, nullptr_t) noexcept; bool operator==(nullptr_t, const executor& e) noexcept; bool operator!=(const executor& a, const executor& b) noexcept; bool operator!=(const executor& e, nullptr_t) noexcept; bool operator!=(nullptr_t, const executor& e) noexcept; // executor specialized algorithms: void swap(executor& a, executor& b) noexcept; } // inline namespace network_v1 } // namespace experimental template<class Alloc> struct uses_allocator<std::experimental::network_v1::executor, Alloc> : true_type {}; } // namespace std
The executor
class provides
a polymorphic wrapper for types that satisfy the Executor
requirements. The target object is the executor
object that is held by the wrapper. The executor
type itself meets the requirements for an Executor.
[Note: To meet the noexcept
requirements for executor copy constructors and move constructors, implementations
may share a target between two or more executor
objects. —end note]
executor() noexcept;
Postconditions:
!*this
.
executor(nullptr_t) noexcept;
Postconditions:
!*this
.
executor(const executor& e) noexcept;
Postconditions:
!*this
if!e
; otherwise,*this
targetse.target()
or a copy ofe.target()
.
executor(executor&& e) noexcept;
Effects: If
!e
,*this
has no target; otherwise, movese.target()
or move-constructs the target ofe
into the target of*this
, leavinge
in a valid state with an unspecified value.
template<class Executor> executor(Executor e);
Requires:
Executor
shall satisfy the Executor requirements.
Effects:
*this
targets a copy ofe
initialized withstd::move(e)
.
Remarks: This function shall not participate in overload resolution unless
is_executor<Executor>::value
is true.
template<class Executor, class Alloc> executor(allocator_arg_t, const Alloc& a, Executor e);
Requires:
Executor
shall satisfy the Executor requirements.Allocator
conforms to theAllocator
requirements (C++ Std, [allocator.requirements]).
Effects:
*this
targets a copy ofe
initialized withstd::move(e)
.
A copy of the allocator argument is used to allocate memory, if necessary, for the internal data structures of the constructed
executor
object.
executor& operator=(const executor& e) noexcept;
Effects:
executor(e).swap(*this)
.
Returns:
*this
.
executor& operator=(executor&& e) noexcept;
Effects: Replaces the target of
*this
with the target ofe
, leavinge
in a valid state with an unspecified value.
Returns:
*this
.
executor& operator=(nullptr_t) noexcept;
Effects:
executor(nullptr).swap(*this)
.
Returns:
*this
.
template<class Executor> executor& operator=(Executor e);
Effects:
executor(std::move(e)).swap(*this)
.
Returns:
*this
.
Remarks: This function shall not participate in overload resolution unless
is_executor<Executor>::value
is true.
~executor();
Effects: If
*this != nullptr
, releases shared ownership of, or destroys, the target of*this
.
void swap(executor& other) noexcept;
Effects: Interchanges the targets of
*this
andother
.
template<class Executor, class Alloc> void assign(Executor e, const Alloc& e);
Effects:
executor(allocator_arg, a, std::move(e)).swap(*this)
.
execution_context& context() noexcept;
Returns:
e.context()
, wheree
is the target object of*this
.
void on_work_started() noexcept;
Effects:
e.on_work_started()
, wheree
is the target object of*this
.
void on_work_finished() noexcept;
Effects:
e.on_work_finished()
, wheree
is the target object of*this
.
template<class Func, class Alloc> void dispatch(Func&& f, const Alloc& a);
Effects:
e.dispatch(g, a)
, wheree
is the target object of*this
, andg
is a function object of unspecified type that, when called asg()
, performsDECAY_COPY(f)()
.
template<class Func, class Alloc> void post(Func&& f, const Alloc& a);
Effects:
e.post(g, a)
, wheree
is the target object of*this
, andg
is a function object of unspecified type that, when called asg()
, performsDECAY_COPY(f)()
.
template<class Func, class Alloc> void defer(Func&& f, const Alloc& a);
Effects:
e.defer(g, a)
, wheree
is the target object of*this
, andg
is a function object of unspecified type that, when called asg()
, performsDECAY_COPY(f)()
.
explicit operator bool() const noexcept;
Returns:
true
if*this
has a target, otherwisefalse
,
const type_info& target_type() const noexcept;
Returns: If
*this
has a target of typeT
,typeid(T)
; otherwise,typeid(void)
.
template<class Executor> Executor* target() noexcept; template<class Executor> const Executor* target() const noexcept;
Requires:
Executor
shall satisfy the Executor requirements.
Returns: If
target_type() == typeid(Executor)
a pointer to the stored executor target; otherwise a null pointer.
bool operator==(const executor& a, const executor& b) noexcept;
Returns:
—true
if!a
and!b
;
—true
ifa
andb
share a target;
—true
ife
andf
are the same type ande == f
, wheree
is the target object ofa
andf
is the target object ofb
;
— otherwisefalse
.
bool operator==(const executor& e, nullptr_t) noexcept; bool operator==(nullptr_t, const executor& e) noexcept;
Returns:
!e
.
bool operator!=(const executor& a, const executor& b) noexcept;
Returns:
!(a == b)
.
bool operator!=(const executor& e, nullptr_t) noexcept; bool operator!=(nullptr_t, const executor& e) noexcept;
Returns:
(bool) e
.
template<class CompletionToken> auto dispatch(CompletionToken&& token);
Let the type
Handler
be the handler function object type determined by performinghandler_type_t<CompletionToken, void()>
.
Requires: The type
Handler
must satisfy theMoveConstructible
requirements (C++ Std, [moveconstructible]) and be callable with zero arguments.
Effects:
— Constructs a function objecthandler
of typeHandler
, initialized withhandler(forward<CompletionToken>(token))
.
— Constructs an objectresult
of typeasync_result<Handler>
, initializing the object asresult(handler)
.
— Obtains the handler's associated executor objectex
by performingget_associated_executor(handler)
.
— Obtains the handler's associated allocator objectalloc
by performingget_associated_allocator(handler)
.
— Performsex.dispatch(std::move(handler), alloc)
.
Returns:
result.get()
.
template<class Executor, class CompletionToken> auto dispatch(const Executor& ex, CompletionToken&& token);
Let the type
Handler
be the handler function object type determined by performinghandler_type_t<CompletionToken, void()>
.
Requires: The type
Handler
must satisfy theMoveConstructible
requirements (C++ Std, [moveconstructible]) and be callable with zero arguments.
Effects:
— Constructs a function objecthandler
of typeHandler
, initialized withhandler(forward<CompletionToken>(token))
.
— Constructs an objectresult
of typeasync_result<Handler>
, initializing the object asresult(handler)
.
— Obtains the handler's associated executor objectex1
by performingget_associated_executor(handler)
.
— Creates a work objectw
by performingmake_work(ex1)
.
— Obtains the handler's associated allocator objectalloc
by performingget_associated_allocator(handler)
.
— Constructs a function objectf
with a function call operator that performsex1.dispatch(std::move(handler), alloc)
followed byw.reset()
.
— Performsex.dispatch(std::move(f), alloc)
.
Returns:
result.get()
.
Remarks: This function shall not participate in overload resolution unless
is_executor<Executor>::value
is true.
template<class ExecutionContext, class CompletionToken> auto dispatch(ExecutionContext& ctx, CompletionToken&& token);
Returns:
std::experimental::network_v1::dispatch(ctx.get_executor(), forward<CompletionToken>(token))
.
Remarks: This function shall not participate in overload resolution unless
is_convertible<ExecutionContext&, execution_context&>::value
is true.
template<class CompletionToken> auto post(CompletionToken&& token);
Let the type
Handler
be the handler function object type determined by performinghandler_type_t<CompletionToken, void()>
.
Requires: The type
Handler
must satisfy theMoveConstructible
requirements (C++ Std, [moveconstructible]) and be callable with zero arguments.
Effects:
— Constructs a function objecthandler
of typeHandler
, initialized withhandler(forward<CompletionToken>(token))
.
— Constructs an objectresult
of typeasync_result<Handler>
, initializing the object asresult(handler)
.
— Obtains the handler's associated executor objectex
by performingget_associated_executor(handler)
.
— Obtains the handler's associated allocator objectalloc
by performingget_associated_allocator(handler)
.
— Performsex.post(std::move(handler), alloc)
.
Returns:
result.get()
.
template<class Executor, class CompletionToken> auto post(const Executor& ex, CompletionToken&& token);
Let the type
Handler
be the handler function object type determined by performinghandler_type_t<CompletionToken, void()>
.
Requires: The type
Handler
must satisfy theMoveConstructible
requirements (C++ Std, [moveconstructible]) and be callable with zero arguments.
Effects:
— Constructs a function objecthandler
of typeHandler
, initialized withhandler(forward<CompletionToken>(token))
.
— Constructs an objectresult
of typeasync_result<Handler>
, initializing the object asresult(handler)
.
— Obtains the handler's associated executor objectex1
by performingget_associated_executor(handler)
.
— Creates a work objectw
by performingmake_work(ex1)
.
— Obtains the handler's associated allocator objectalloc
by performingget_associated_allocator(handler)
.
— Constructs a function objectf
with a function call operator that performsex1.dispatch(std::move(handler), alloc)
followed byw.reset()
.
— Performsex.post(std::move(f), alloc)
.
Returns:
result.get()
.
Remarks: This function shall not participate in overload resolution unless
is_executor<Executor>::value
is true.
template<class ExecutionContext, class CompletionToken> auto post(ExecutionContext& ctx, CompletionToken&& token);
Returns:
std::experimental::network_v1::post(ctx.get_executor(), forward<CompletionToken>(token))
.
Remarks: This function shall not participate in overload resolution unless
is_convertible<ExecutionContext&, execution_context&>::value
is true.
template<class CompletionToken> auto defer(CompletionToken&& token);
Let the type
Handler
be the handler function object type determined by performinghandler_type_t<CompletionToken, void()>
.
Requires: The type
Handler
must satisfy theMoveConstructible
requirements (C++ Std, [moveconstructible]) and be callable with zero arguments.
Effects:
— Constructs a function objecthandler
of typeHandler
, initialized withhandler(forward<CompletionToken>(token))
.
— Constructs an objectresult
of typeasync_result<Handler>
, initializing the object asresult(handler)
.
— Obtains the handler's associated executor objectex
by performingget_associated_executor(handler)
.
— Obtains the handler's associated allocator objectalloc
by performingget_associated_allocator(handler)
.
— Performsex.defer(std::move(handler), alloc)
.
Returns:
result.get()
.
template<class Executor, class CompletionToken> auto defer(const Executor& ex, CompletionToken&& token);
Let the type
Handler
be the handler function object type determined by performinghandler_type_t<CompletionToken, void()>
.
Requires: The type
Handler
must satisfy theMoveConstructible
requirements (C++ Std, [moveconstructible]) and be callable with zero arguments.
Effects:
— Constructs a function objecthandler
of typeHandler
, initialized withhandler(forward<CompletionToken>(token))
.
— Constructs an objectresult
of typeasync_result<Handler>
, initializing the object asresult(handler)
.
— Obtains the handler's associated executor objectex1
by performingget_associated_executor(handler)
.
— Creates a work objectw
by performingmake_work(ex1)
.
— Obtains the handler's associated allocator objectalloc
by performingget_associated_allocator(handler)
.
— Constructs a function objectf
with a function call operator that performsex1.dispatch(std::move(handler), alloc)
followed byw.reset()
.
— Performsex.defer(std::move(f), alloc)
.
Returns:
result.get()
.
Remarks: This function shall not participate in overload resolution unless
is_executor<Executor>::value
is true.
template<class ExecutionContext, class CompletionToken> auto defer(ExecutionContext& ctx, CompletionToken&& token);
Returns:
std::experimental::network_v1::defer(ctx.get_executor(), forward<CompletionToken>(token))
.
Remarks: This function shall not participate in overload resolution unless
is_convertible<ExecutionContext&, execution_context&>::value
is true.
namespace std { namespace experimental { inline namespace network_v1 { template<class Executor> class strand { public: // types: typedef Executor inner_executor_type; // construct / copy / destroy: strand(); explicit strand(Executor ex); strand(const strand& other); strand(strand&& other); template<class OtherExecutor> strand(const strand<OtherExecutor>& other); template<class OtherExecutor> strand(strand<OtherExecutor>&& other); strand& operator=(const strand& other); strand& operator=(strand&& other); template<class OtherExecutor> strand& operator=(const strand<OtherExecutor>& other); template<class OtherExecutor> strand& operator=(strand<OtherExecutor>&& other); ~strand(); // strand operations: inner_executor_type get_inner_executor() const noexcept; bool running_in_this_thread() const noexcept; execution_context& context() noexcept; void on_work_started() noexcept; void on_work_finished() noexcept; template<class Func, class Alloc> void dispatch(Func&& f, const Alloc& a); template<class Func, class Alloc> void post(Func&& f, const Alloc& a); template<class Func, class Alloc> void defer(Func&& f, const Alloc& a); private: Executor inner_ex_; // exposition only }; bool operator==(const strand<Executor>& a, const strand<Executor>& b); bool operator!=(const strand<Executor>& a, const strand<Executor>& b); } // inline namespace network_v1 } // namespace experimental } // namespace std
strand<Executor>
is a wrapper around an object of type Executor
satisfying Executor requirements.
strand<Executor>
satisfies the Executor requirements.
A strand provides guarantees of ordering and non-concurrency. Given:
— strand objects s1
and
s2
such that s1 == s2
— a function object f1
added
to the strand s1
using
post
or defer
,
or using dispatch
when
s1.running_in_this_thread()
== false
— a function object f2
added
to the strand s2
using
post
or defer
,
or using dispatch
when
s2.running_in_this_thread()
== false
then the implementation shall invoke f1
and f2
such that:
— the invocation of f1
is
not concurrent with the invocation of f2
— the invocation of f1
synchronizes
with the invocation of f2
.
Furthermore, if the addition of f1
happens before the addition of f2
,
then the invocation of f1
happens before the invocation of f2
.
The strand copy constructors, comparison operators, and member functions shall not introduce data races as a result of concurrent calls to those functions from different threads.
If any function f
executed
by the strand throws an exception, the subsequent strand state shall be
as if f
had exited without
throwing an exception.
strand();
Effects: Constructs an object of class
strand<Executor>
that represents a unique ordered, non-concurrent state. Initializesinner_ex_
withinner_ex_()
.
Remarks: This overload shall not participate in overload resolution unless
Executor
satisfies theDefaultConstructible
requirements (C++ Std, [defaultconstructible]).
explicit strand(Executor ex);
Effects: Constructs an object of class
strand<Executor>
that represents a unique ordered, non-concurrent state. Initializesinner_ex_
withinner_ex_(ex)
.
strand(const strand& other);
Effects: Constructs an object of class
strand<Executor>
. Initalizesinner_ex_
withinner_ex_(other.inner_ex_)
.
Postconditions:
—*this == other
—get_inner_executor() == other.get_inner_executor()
strand(strand&& other);
Effects: Constructs an object of class
strand<Executor>
. Initalizesinner_ex_
withinner_ex_(std::move(other.inner_ex_))
.
Postconditions:
—*this
is equal to the prior value ofother
—get_inner_executor() == other.get_inner_executor()
template<class OtherExecutor> strand(const strand<OtherExecutor>& other);
Requires:
OtherExecutor
is convertible toExecutor
.
Effects: Constructs an object of class
strand<Executor>
. Initalizesinner_ex_
withinner_ex_(other.inner_ex_)
.
Postconditions:
*this == other
.
template<class OtherExecutor> strand(strand<OtherExecutor>&& other);
Requires:
OtherExecutor
is convertible toExecutor
.
Effects: Constructs an object of class
strand<Executor>
. Initalizesinner_ex_
withinner_ex_(other.inner_ex_)
.
Postconditions:
*this
is equal to the prior value ofother
.
strand& operator=(const strand& other);
Requires:
Executor
isAssignable
(C++ Std [assignable]).
Postconditions:
—*this == other
—get_inner_executor() == other.get_inner_executor()
Returns:
*this
.
strand& operator=(strand&& other);
Requires:
Executor
isAssignable
(C++ Std [assignable]).
Postconditions:
—*this
is equal to the prior value ofother
—get_inner_executor() == other.get_inner_executor()
Returns:
*this
.
template<class OtherExecutor> strand& operator=(const strand<OtherExecutor>& other);
Requires:
OtherExecutor
is convertible toExecutor
.Executor
isAssignable
(C++ Std [assignable]).
Effects: Equivalent to
strand<Executor>::operator=(Executor(other))
.
Returns:
*this
.
template<class OtherExecutor> strand& operator=(strand<OtherExecutor>&& other);
Requires:
OtherExecutor
is convertible toExecutor
.Executor
isAssignable
(C++ Std [assignable]).
Effects: Equivalent to
strand<Executor>::operator=(Executor(std::move(other)))
.
Returns:
*this
.
~strand();
Effects: Destroys an object of class
strand<Executor>
. Function objects that were added to the strand but have not yet been executed shall still be executed in a way that meets the guarantees of ordering and non-concurrency.
inner_executor_type get_inner_executor() const noexcept;
Returns:
inner_ex_
.
bool running_in_this_thread() const noexcept;
Returns:
true
if the current thread of execution is invoking a function that was submitted to the strand, or to any other strand objects
such thats == *this
, usingdispatch
,post
ordefer
; otherwisefalse
.
execution_context& context() noexcept;
Returns:
inner_ex_.context()
.
void on_work_started() noexcept;
Effects: Calls
inner_ex_.on_work_started()
.
void on_work_finished() noexcept;
Effects: Calls
inner_ex_.on_work_finished()
.
template<class Func, class Alloc> void dispatch(Func&& f, const Alloc& a);
Effects: If
running_in_this_thread()
is true, callsDECAY_COPY
(forward<Func>(f))()
. Otherwise, requests invocation off
, as if by forwarding the function objectf
and allocatora
to the executorinner_ex_
, such that the guarantees of ordering and non-concurrency are met.
If
f
exits via an exception, and the execution off
is performed in the current thread and beforedispatch
returns, the exception shall propagate to the caller ofdispatch()
template<class Func, class Alloc> void post(Func&& f, const Alloc& a);
Effects: Requests invocation of
f
, as if by forwarding the function objectf
and allocatora
to the executorinner_ex_
, such that the guarantees of ordering and non-concurrency are met.
template<class Func, class Alloc> void defer(Func&& f, const Alloc& a);
Effects: Requests invocation of
f
, as if by forwarding the function objectf
and allocatora
to the executorinner_ex_
, such that the guarantees of ordering and non-concurrency are met.
namespace std { namespace experimental { inline namespace network_v1 { template<class Allocator = allocator<void>> class use_future_t { public: // use_future_t types: typedef Allocator allocator_type; // use_future_t members: constexpr use_future_t() noexcept; explicit use_future_t(const Allocator& a) noexcept; template<class OtherAllocator> use_future_t<OtherAllocator> operator[](const OtherAllocator& a) const noexcept; allocator_type get_allocator() const noexcept; }; } // inline namespace network_v1 } // namespace experimental } // namespace std
The class template use_future_t
defines a set of completion token
types for use with asynchronous operations.
constexpr use_future_t() noexcept;
Effects: Constructs a
use_future_t
with default-constructed allocator.
explicit use_future_t(const Allocator& a) noexcept;
Effects: Constructs an object of type
use_future_t
with post-conditionget_allocator() == a
.
template<class OtherAllocator> use_future_t<OtherAllocator> operator[](const OtherAllocator& a) const noexcept;
Returns: A
use_future_t
object whereget_allocator() == a
.
allocator_type get_allocator() const noexcept;
Returns: The associated allocator object.
template<class Allocator, class R, class... Args> struct handler_type<use_future_t<Allocator>, R(Args...)> { typedef see below type; };
An object t1
of the nested
function object type type
is an asynchronous provider with an associated shared state (C++Std,
[futures.state]). The type type
provides type::operator()
such that the expression t1(declval<Args>()...)
is well formed.
The implementation shall specialize associated_executor
for type
. For function
objects executed using the associated executor's dispatch()
, post()
or defer()
functions, any exception thrown is
caught by the executor and stored in the associated shared state.
The implementation shall specialize async_result
for type
such that, when
an async_result
object
r1
is constructed from
t1
, the expression r1.get()
returns a future with the same shared state as t1
.
The semantics of async_result::type
and type::operator()
are defined in the table below. In this table, N
is
the value of sizeof...(Args)
;
let i
be in the range [0
..N
)
and let Ti
be the i
th
type in Args
; let Ui
be decay<Ti>::type
for
each type Ti
in Args
; and let ai
be the i
th argument to type::operator()
.
Table 7. handler_type<use_future_t<Allocator>, R(Args...)>::type semantics
|
|
|
|
---|---|---|---|
0 |
|
Makes the shared state ready. | |
1 |
|
|
If |
1 |
|
|
If |
1 |
all other types |
|
Atomically stores |
2 |
|
|
If |
2 |
|
|
If |
2 |
all other types |
|
Atomically stores the result of |
>2 |
|
|
If |
>2 |
|
|
If |
>2 |
all other types |
|
Atomically stores the result of |
namespace std { namespace experimental { inline namespace network_v1 { template<class R, class... Args> class async_result<packaged_task<R(Args...)>> { public: typedef future<R> type; async_result(packaged_task<R(Args...)>& t); async_result(const async_result&) = delete; async_result& operator=(const async_result&) = delete; type get(); private: type future_; // exposition only }; } // inline namespace network_v1 } // namespace experimental } // namespace std
The implementation shall provide a specialization of async_result
that meets the async_result
specialization requirements.
async_result(packaged_task<R(Args...)>& t);
Effects: Initializes
future_
witht.get_future()
.
type get();
Returns:
std::move(future_)
.
namespace std { namespace experimental { inline namespace network_v1 { template<class Signature, class Alloc> class packaged_handler : public packaged_task<Signature> { public: // packaged_handler types: typedef Alloc allocator_type; // packaged_handler constructors: template<class Func> explicit packaged_handler(packaged_token<Func, Alloc>&& token); // packaged_handler operations: allocator_type get_allocator() const noexcept; private: Alloc allocator_; // exposition only }; template<class Signature, class Alloc> class async_result<packaged_handler<Signature, Alloc>>; } // inline namespace network_v1 } // namespace experimental } // namespace std
template<class Func> explicit packaged_handler(packaged_token<Func, Alloc>&& token);
Effects: Constructs an object of class
packaged_handler<Signature, Alloc>
, initializing the base class withpackaged_task<Signature>(std::move(token.f_))
and initializingallocator_
withtoken.allocator_
.
allocator_type get_allocator() const noexcept;
Returns:
allocator_
.
namespace std { namespace experimental { inline namespace network_v1 { template<class Signature, class Alloc> class async_result<packaged_handler<Signature, Alloc>> : public async_result<packaged_task<Signature>> { public: explicit async_result(packaged_handler<Signature, Alloc>& h); }; } // inline namespace network_v1 } // namespace experimental } // namespace std
The implementation shall provide a specialization of async_result
that meets the async_result
specialization requirements.
explicit async_result(packaged_handler<Signature, Alloc>& h);
Effects: Initializes the base class with
h
.
namespace std { namespace experimental { inline namespace network_v1 { template<class Func, class Alloc = allocator<void>> class packaged_token { public: // packaged_token types: typedef Alloc allocator_type; // packaged_token constructors: explicit packaged_token(Func f); packaged_token(Func f, const Alloc& a); // packaged_token operations: allocator_type get_allocator() const noexcept; private: Func f_; // exposition only Alloc allocator_; // exposition only }; template<class Func, class Alloc, class R, class... Args> struct handler_type<packaged_token<Func, Alloc>, R(Args...)> { typedef packaged_handler<result_of_t<Func(Args...)>(Args...), Alloc> type; }; } // inline namespace network_v1 } // namespace experimental } // namespace std
explicit packaged_token(Func f);
Effects: Constructs an object of class
packaged_token<Func, Alloc>
, initializingf_
withstd::move(f)
and default constructingallocator_
.
packaged_token(Func f, const Alloc& a);
Effects: Constructs an object of class
packaged_token<Func, Alloc>
, initializingf_
withstd::move(f)
andallocator_
witha
.
namespace std { namespace experimental { inline namespace network_v1 { class io_service; } // inline namespace network_v1 } // namespace experimental } // namespace std
namespace std { namespace experimental { inline namespace network_v1 { class io_service : public execution_context { public: // types: class executor_type; // construct / copy / destroy: io_service(); explicit io_service(std::size_t concurrency_hint); io_service(const io_service&) = delete; io_service& operator=(const io_service&) = delete; ~io_service(); // io_service operations: executor_type get_executor() noexcept; size_t run(); template<class Rep, class Period> size_t run_for(const chrono::duration<Rep, Period>& rel_time); template<class Clock, class Duration> size_t run_until(const chrono::time_point<Clock, Duration>& abs_time); size_t run_one(); template<class Rep, class Period> size_t run_one_for(const chrono::duration<Rep, Period>& rel_time); template<class Clock, class Duration> size_t run_one_until(const chrono::time_point<Clock, Duration>& abs_time); size_t poll(); size_t poll_one(); void stop(); bool stopped() const; void restart(); }; } // inline namespace network_v1 } // namespace experimental } // namespace std
Synchronous operations
on I/O objects implicitly run the io_service
object for an individual operation. The io_service
functions run
, run_for
, run_until
,
run_one
, run_one_for
, run_one_until
,
poll
or poll_one
must be called for the io_service
to perform asynchronous
operations on behalf of a C++ program. Notification that an asynchronous
operation has completed is delivered by execution of the associated handler
function object, as determined by the requirements for asynchronous
operations.
An object of type io_service
has an associated executor object, meeting the Executor
type requirements, of type io_service::executor_type
and obtainable via the io_service
object's get_executor
member
function.
For an object of type io_service
,
outstanding work is defined as the sum of:
— the total number of calls to the io_service
executor's on_work_started
function, less the total number of calls to the on_work_finished
function;
— the number of function objects that have been added to the io_service
via the io_service
executor, but not yet executed; and
— the number of function objects that are currently being executed by the
io_service
.
If at any time the outstanding work falls to 0
,
the io_service
is stopped
as if by stop()
.
The io_service
member functions
get_executor
, run
, run_for
,
run_until
, run_one
, run_one_for
,
run_one_until
, poll
, poll_one
,
stop
, and stopped
, and the io_service::executor_type
copy constructors, member functions and comparison operators, shall not
introduce data races as a result of concurrent calls to those functions
from different threads. [Note: The restart
member function is excluded from these thread safety requirements. —end
note]
io_service(); explicit io_service(std::size_t concurrency_hint);
Effects: Creates an object of class
io_service
.
Remarks: The
concurrency_hint
parameter is a suggestion to the implementation on the number of threads that should process asynchronous operations and execute function objects.
~io_service();
Effects: Destroys an object of class
io_service
.
executor_type get_executor() noexcept;
Returns: An executor that may be used for submitting function objects to the
io_service
.
size_t run();
Requires: Must not be called from a thread that is currently calling one of
run
,run_for
,run_until
,run_one
,run_one_for
,run_one_until
,poll
, orpoll_one
.
Effects: Equivalent to:
size_t n = 0; while (run_one()) if (n != numeric_limits<size_t>::max()) ++n;
Returns:
n
.
template<class Rep, class Period> size_t run_for(const chrono::duration<Rep, Period>& rel_time);
Effects: Equivalent to:
return run_until(chrono::steady_clock::now() + rel_time);
template<class Clock, class Duration> size_t run_until(const chrono::time_point<Clock, Duration>& abs_time);
Effects: Equivalent to:
size_t n = 0; while (run_one_until(abs_time)) if (n != numeric_limits<size_t>::max()) ++n;
Returns:
n
.
size_t run_one();
Requires: Must not be called from a thread that is currently calling one of
run
,run_for
,run_until
,run_one
,run_one_for
,run_one_until
,poll
, orpoll_one
.
Effects: If the
io_service
object has no oustanding work, performsstop()
. Otherwise, blocks while the io_service has outstanding work, or until theio_service
is stopped, or until one function object has been executed.
If an executed function object throws an exception, the exception shall be allowed to propagate to the caller of
run_one()
. Theio_service
state shall be as if the function object had returned normally.
Returns:
1
if a function object was executed, otherwise0
.
Notes: This function may invoke additional handlers through nested calls to the
io_service
executor'sdispatch
member function. These do not count towards the return value.
template<class Rep, class Period> size_t run_one_for(const chrono::duration<Rep, Period>& rel_time);
Effects: Equivalent to:
return run_until(chrono::steady_clock::now() + rel_time);
Returns:
1
if a function object was executed, otherwise0
.
template<class Clock, class Duration> size_t run_one_until(const chrono::time_point<Clock, Duration>& abs_time);
Effects: If the
io_service
object has no oustanding work, performsstop()
. Otherwise, blocks while the io_service has outstanding work, or until the expiration of the absolute timeout (C++ Std, [thread.req.timing]) specified byabs_time
, or until theio_service
is stopped, or until one function object has been executed.
If an executed function object throws an exception, the exception shall be allowed to propagate to the caller of
run_one()
. Theio_service
state shall be as if the function object had returned normally.
Returns:
1
if a function object was executed, otherwise0
.
Notes: This function may invoke additional handlers through nested calls to the
io_service
executor'sdispatch
member function. These do not count towards the return value.
size_t poll();
Effects: Equivalent to:
size_t n = 0; while (poll_one()) if (n != numeric_limits<size_t>::max()) ++n;
Returns:
n
.
size_t poll_one();
Effects: If the
io_service
object has no oustanding work, performsstop()
. Otherwise, if there is a function object ready for immediate execution, executes it.
If an executed function object throws an exception, the exception shall be allowed to propagate to the caller of
poll_one()
. Theio_service
state shall be as if the function object had returned normally.
Returns:
1
if a handler was invoked, otherwise0
.
Notes: This function may invoke additional handlers through nested calls to the
io_service
executor'sdispatch
member function. These do not count towards the return value.
void stop();
Effects: Stops the
io_service
. Concurrent calls torun
,run_for
,run_until
,run_one
,run_one_for
,run_one_until
,poll
orpoll_one
will end as soon as possible. If a call torun
,run_for
,run_until
,run_one
,run_one_for
,run_one_until
,poll
orpoll_one
is currently executing a function object, the call will end only after completion of that function object. The call tostop()
returns without waiting for concurrent calls torun
,run_for
,run_until
,run_one
,run_one_for
,run_one_until
,poll
orpoll_one
to complete.
Postconditions:
stopped() == true
.
[Note: When
stopped() == true
, subsequent calls torun
,run_for
,run_until
,run_one
,run_one_for
,run_one_until
,poll
orpoll_one
will exit immediately with a return value of0
, without executing any function objects. Anio_service
remains in the stopped state until a call torestart()
. —end note]
void restart();
Postconditions:
stopped() == false
.
namespace std { namespace experimental { inline namespace network_v1 { class io_service::executor_type { public: // construct / copy / destroy: executor_type(const executor_type& other) noexcept; executor_type(executor_type&& other) noexcept; executor_type& operator=(const executor_type& other) noexcept; executor_type& operator=(executor_type&& other) noexcept; ~executor_type(); // executor operations: bool running_in_this_thread() const noexcept; io_service& context() noexcept; void on_work_started() noexcept; void on_work_finished() noexcept; template<class Func, class Alloc> void dispatch(Func&& f, const Alloc& a); template<class Func, class Alloc> void post(Func&& f, const Alloc& a); template<class Func, class Alloc> void defer(Func&& f, const Alloc& a); }; bool operator==(const io_service::executor_type& a, const io_service::executor_type& b) noexcept; bool operator!=(const io_service::executor_type& a, const io_service::executor_type& b) noexcept; template<> struct is_executor<io_service::executor_type> : true_type {}; } // inline namespace network_v1 } // namespace experimental } // namespace std
io_service::executor_type
is a type satisfying Executor requirements. Objects of
type io_service::executor_type
are associated with an
io_service
, and function
objects submitted using the dispatch
,
post
or defer
member functions will be executed by the io_service
from within the run
, run_for
, run_until
,
run_one
, run_one_for
, run_one_until
,
poll
or poll_one
functions.
executor_type(const executor_type& other) noexcept;
Effects: Constructs an object of class
io_service::executor_type
.
Postconditions:
*this == other
.
executor_type(executor_type&& other) noexcept;
Effects: Constructs an object of class
io_service::executor_type
.
Postconditions:
*this
is equal to the prior value ofother
.
executor_type& operator=(const executor_type& other) noexcept;
Postconditions:
*this == other
.
Returns:
*this
.
executor_type& operator=(executor_type&& other) noexcept;
Postconditions:
*this
is equal to the prior value ofother
.
Returns:
*this
.
bool running_in_this_thread() const noexcept;
Returns:
true
if the current thread of execution is invoking therun
,run_for
,run_until
,run_one
,run_one_for
,run_one_until
,poll
orpoll_one
function of the associatedio_service
object.
io_service& context() noexcept;
Returns: A reference to the associated
io_service
object.
void on_work_started() noexcept;
Effects: Increases the count of outstanding work associated with the
io_service
.
void on_work_finished() noexcept;
Effects: Decreases the count of outstanding work associated with the
io_service
.
template<class Func, class Alloc> void dispatch(Func&& f, const Alloc& a);
Effects: If
running_in_this_thread()
is true, callsDECAY_COPY
(forward<Func>(f))()
. Otherwise, requests execution off
.
If
f
exits via an exception, and the execution off
is performed in the current thread and beforedispatch
returns, the exception shall propagate to the caller ofdispatch
.
template<class Func, class Alloc> void post(Func&& f, const Alloc& a);
Effects: Requests execution of
f
.
template<class Func, class Alloc> void defer(Func&& f, const Alloc& a);
Effects: Requests execution of
f
.
This subclause defines components for performing timer operations.
[Example: Performing a synchronous wait operation on a timer:
io_service i; steady_timer t(i); t.expires_after(seconds(5)); t.wait();
—end example]
[Example: Performing an asynchronous wait operation on a timer:
void handler(error_code ec) { ... } ... io_service i; steady_timer t(i); t.expires_after(seconds(5)); t.async_wait(handler); i.run();
—end example]
#include <chrono> namespace std { namespace experimental { inline namespace network_v1 { template<class Clock> struct wait_traits; template<class Clock, class WaitTraits = wait_traits<Clock>> class basic_waitable_timer; typedef basic_waitable_timer<chrono::system_clock> system_timer; typedef basic_waitable_timer<chrono::steady_clock> steady_timer; typedef basic_waitable_timer<chrono::high_resolution_clock> high_resolution_timer; } // inline namespace network_v1 } // namespace experimental } // namespace std
In the table below, X
denotes a wait traits class for a type Clock
meeting the Clock
requirements
(C++ Std [time.clock.req]); t
denotes a value of type Clock::time_point
;
and d
denotes a value
of type Clock::duration
.
Table 8. WaitTraits requirements
expression |
return type |
assertion/note |
---|---|---|
|
|
Returns a |
|
|
Returns a |
namespace std { namespace experimental { inline namespace network_v1 { template<class Clock> struct wait_traits { static typename Clock::duration to_wait_duration( const typename Clock::duration& d); static typename Clock::duration to_wait_duration( const typename Clock::time_point& t); }; } // inline namespace network_v1 } // namespace experimental } // namespace std
Class template wait_traits
satisfies the WaitTraits
type requirements. Template argument Clock
is a type meeting the Clock
requirements (C++ Std [time.clock.req]).
A program may specialize this template if the Clock
template parameter in the specialization is a user-defined type.
static typename Clock::duration to_wait_duration( const typename Clock::duration& d);
Returns:
d
.
static typename Clock::duration to_wait_duration( const typename Clock::time_point& t);
Returns: If
Clock::now() + Clock::duration::max() < t
,Clock::duration::max()
; ifClock::now() + Clock::duration::min() > t
,Clock::duration::min()
; otherwise,t - Clock::now()
.
namespace std { namespace experimental { inline namespace network_v1 { template<class Clock, class WaitTraits = wait_traits<Clock>> class basic_waitable_timer { public: // types: typedef io_service::executor_type executor_type; typedef Clock clock_type; typedef typename Clock::duration duration; typedef typename Clock::time_point time_point; typedef WaitTraits traits_type; // construct / copy / destroy: explicit basic_waitable_timer(io_service& ios); basic_waitable_timer(io_service& ios, const time_point& t); basic_waitable_timer(io_service& ios, const duration& d); basic_waitable_timer(const basic_waitable_timer&) = delete; basic_waitable_timer(basic_waitable_timer&& rhs); ~basic_waitable_timer(); basic_waitable_timer& operator=(const basic_waitable_timer&) = delete; basic_waitable_timer& operator=(basic_waitable_timer&& rhs); // basic_waitable_timer operations: executor_type get_executor() noexcept; size_t cancel(); size_t cancel_one(); time_point expiry() const; size_t expires_at(const time_point& t); size_t expires_after(const duration& d); void wait(); void wait(error_code& ec); template<class CompletionToken> auto async_wait(CompletionToken&& token); }; } // inline namespace network_v1 } // namespace experimental } // namespace std
explicit basic_waitable_timer(io_service& ios);
Effects: Constructs an object of class
basic_waitable_timer<Clock, WaitTraits>
.
Postconditions:
—get_executor() == ios.get_executor()
.
—expiry() == Clock::time_point()
.
basic_waitable_timer(io_service& ios, const time_point& t);
Effects: Constructs an object of class
basic_waitable_timer<Clock, WaitTraits>
, setting the expiry time as if by callingthis->expires_at(t)
.
Postconditions:
get_executor() == ios.get_executor()
.
basic_waitable_timer(io_service& ios, const duration& d);
Effects: Constructs an object of class
basic_waitable_timer<Clock, WaitTraits>
, setting the expiry time as if by callingthis->expires_at(d)
.
Postconditions:
get_executor() == ios.get_executor()
.
basic_waitable_timer(basic_waitable_timer&& rhs);
Effects: Move constructs an object of class
basic_waitable_timer<Clock, WaitTraits>
that refers to the state originally represented byrhs
.
Postconditions:
—get_executor() == rhs.get_executor()
.
—expiry()
returns the same value asrhs.expiry()
prior to the constructor invocation.
—rhs.expiry() == Clock::time_point()
.
~basic_waitable_timer();
Effects: Destroys the timer, cancelling any asynchronous wait operations associated with the timer as if by calling
cancel()
.
basic_waitable_timer& operator=(basic_waitable_timer&& rhs);
Effects: Cancels any outstanding asynchronous operations associated with
*this
as if by callingcancel()
, then moves into*this
the state originally represented byrhs
.
Postconditions:
—get_executor() == rhs.get_executor()
.
—expiry()
returns the same value asrhs.expiry()
prior to the assignment.
—rhs.expiry() == Clock::time_point()
.
Returns:
*this
.
executor_type get_executor() noexcept;
Returns: The associated executor.
size_t cancel();
Effects: Causes any outstanding asynchronous wait operations to complete as soon as possible. Handlers for cancelled operations shall be passed an error code
ec
such thatec == errc::operation_canceled
holds true.
Returns: The number of operations that were cancelled.
size_t cancel_one();
Effects: Causes the oldest outstanding asynchronous wait operation, if any, to complete as soon as possible. The handler for the cancelled operation shall be passed an error code
ec
such thatec == errc::operation_canceled
holds true.
Returns: The number of operations that were cancelled.
time_point expiry() const;
Returns: The expiry time associated with the timer, as previously set using
expires_at()
orexpires_after()
.
Returns:
this->service.expires_at(this->implementation)
.
size_t expires_at(const time_point& t);
Effects: Sets the expiry time associated with the timer. Implicitly cancels asynchronous wait operations, as if by calling
cancel()
.
Returns: The number of operations that were cancelled.
Postconditions:
expiry() == t
.
size_t expires_after(const duration& d);
Returns:
expires_at(Clock::now() + d)
.
void wait(); void wait(error_code& ec);
Effects: Establishes the postcondition as if by repeatedly blocking the calling thread for the relative time produced by
WaitTraits::to_wait_duration(expiry())
.
Postconditions:
!!ec || !(Clock::now() < expiry())
.
template<class CompletionToken> auto async_wait(CompletionToken&& token);
Completion signature:
void(error_code ec)
.
Effects: Initiates an asynchronous wait operation such that the handler is submitted for execution only when the condition
!!ec || !(Clock::now() < expiry())
holds.
namespace std { namespace experimental { inline namespace network_v1 { enum class stream_errc { eof = implementation defined, not_found = implementation defined }; const error_category& stream_category() noexcept; error_code make_error_code(stream_errc e) noexcept; error_condition make_error_condition(stream_errc e) noexcept; class mutable_buffer; class const_buffer; class mutable_buffers_1; class const_buffers_1; // buffer type traits: template<class T> is_mutable_buffer_sequence; template<class T> is_const_buffer_sequence; template<class T> is_dynamic_buffer_sequence; // buffer conversions: template<class T> T buffer_cast(const mutable_buffer& b) noexcept; template<class T> T buffer_cast(const const_buffer& b) noexcept; // buffer size: size_t buffer_size(const mutable_buffer& b) noexcept; size_t buffer_size(const const_buffer& b) noexcept; template<class ConstBufferSequence> size_t buffer_size(const ConstBufferSequence& buffers) noexcept; // buffer copy: size_t buffer_copy(const mutable_buffer& dest, const const_buffer& source) noexcept; size_t buffer_copy(const mutable_buffer& dest, const const_buffer& source, size_t max_size) noexcept; template<class ConstBufferSequence> size_t buffer_copy(const mutable_buffer& dest, const ConstBufferSequence& source) noexcept; template<class ConstBufferSequence> size_t buffer_copy(const mutable_buffer& dest, const ConstBufferSequence& source, size_t max_size) noexcept; template<class MutableBufferSequence> size_t buffer_copy(const MutableBufferSequence& dest, const const_buffer& source) noexcept; template<class MutableBufferSequence> size_t buffer_copy(const MutableBufferSequence& dest, const const_buffer& source, size_t max_size) noexcept; template<class MutableBufferSequence, class ConstBufferSequence> size_t buffer_copy(const MutableBufferSequence& dest, const ConstBufferSequence& source) noexcept; template<class MutableBufferSequence, class ConstBufferSequence> size_t buffer_copy(const MutableBufferSequence& dest, const ConstBufferSequence& source, max_size) noexcept; // buffer arithmetic: mutable_buffer operator+(const mutable_buffer& b, size_t n) noexcept; mutable_buffer operator+(size_t n, const mutable_buffer& b) noexcept; const_buffer operator+(const const_buffer&, size_t n) noexcept; const_buffer operator+(size_t, const const_buffer&) noexcept; mutable_buffers_1 operator+(const mutable_buffers_1& b, size_t n) noexcept; mutable_buffers_1 operator+(size_t n, const mutable_buffers_1& b) noexcept; const_buffers_1 operator+(const const_buffers_1&, size_t n) noexcept; const_buffers_1 operator+(size_t, const const_buffers_1&) noexcept; // buffer creation: mutable_buffers_1 buffer(void* p, size_t n) noexcept; const_buffers_1 buffer(const void* p, size_t n) noexcept; mutable_buffers_1 buffer(const mutable_buffer& b) noexcept; mutable_buffers_1 buffer(const mutable_buffer& b, size_t n) noexcept; const_buffers_1 buffer(const const_buffer& b) noexcept; const_buffers_1 buffer(const const_buffer& b, size_t n) noexcept; template<class T, size_t N> mutable_buffers_1 buffer(T (&arr)[N]) noexcept; template<class T, size_t N> mutable_buffers_1 buffer(T (&arr)[N], size_t n) noexcept; template<class T, size_t N> const_buffers_1 buffer(const T (&arr)[N]) noexcept; template<class T, size_t N> const_buffers_1 buffer(const T (&arr)[N], size_t n) noexcept; template<class T, size_t N> mutable_buffers_1 buffer(array<T, N>& arr) noexcept; template<class T, size_t N> mutable_buffers_1 buffer(array<T, N>& arr, size_t n) noexcept; template<class T, size_t N> const_buffers_1 buffer(array<const T, N>& arr) noexcept; template<class T, size_t N> const_buffers_1 buffer(array<const T, N>& arr, size_t n) noexcept; template<class T, size_t N> const_buffers_1 buffer(const array<T, N>& arr) noexcept; template<class T, size_t N> const_buffers_1 buffer(const array<T, N>& arr, size_t n) noexcept; template<class T, class Allocator> mutable_buffers_1 buffer(vector<T, Allocator>& vec) noexcept; template<class T, class Allocator> mutable_buffers_1 buffer(vector<T, Allocator>& vec, size_t n) noexcept; template<class T, class Allocator> const_buffers_1 buffer(const vector<T, Allocator>& vec) noexcept; template<class T, class Allocator> const_buffers_1 buffer(const vector<T, Allocator>& vec, size_t n) noexcept; template<class CharT, class Traits, class Allocator> mutable_buffers_1 buffer(basic_string<CharT, Traits, Allocator>& str) noexcept; template<class CharT, class Traits, class Allocator> mutable_buffers_1 buffer(basic_string<CharT, Traits, Allocator>& str, size_t n) noexcept; template<class CharT, class Traits, class Allocator> const_buffers_1 buffer(const basic_string<CharT, Traits, Allocator>& str) noexcept; template<class CharT, class Traits, class Allocator> const_buffers_1 buffer(const basic_string<CharT, Traits, Allocator>& str, size_t n) noexcept; template<class CharT, class Traits> const_buffers_1 buffer(const basic_string_view<CharT, Traits>& str) noexcept; template<class CharT, class Traits, class Allocator> const_buffers_1 buffer(const basic_string_view<CharT, Traits>& str, size_t n) noexcept; template<class T, Allocator> class dynamic_vector_buffer; template<class CharT, class Traits, Allocator> class dynamic_string_buffer; // dynamic buffer creation: template<class T, class Allocator> dynamic_vector_buffer<T, Allocator> dynamic_buffer(vector<T, Allocator>& vec) noexcept; template<class T, class Allocator> dynamic_vector_buffer<T, Allocator> dynamic_buffer(vector<T, Allocator>& vec, size_t n) noexcept; template<class CharT, class Traits, class Allocator> dynamic_string_buffer<CharT, Traits, Allocator> dynamic_buffer(basic_string<CharT, Traits, Allocator>& str) noexcept; template<class CharT, class Traits, class Allocator> dynamic_string_buffer<CharT, Traits, Allocator> dynamic_buffer(basic_string<CharT, Traits, Allocator>& str, size_t n) noexcept; class transfer_all; class transfer_at_least; class transfer_exactly; // synchronous read operations: template<class SyncReadStream, class MutableBufferSequence> size_t read(SyncReadStream& stream, const MutableBufferSequence& buffers); template<class SyncReadStream, class MutableBufferSequence> size_t read(SyncReadStream& stream, const MutableBufferSequence& buffers, error_code& ec); template<class SyncReadStream, class MutableBufferSequence, class CompletionCondition> size_t read(SyncReadStream& stream, const MutableBufferSequence& buffers, CompletionCondition completion_condition); template<class SyncReadStream, class MutableBufferSequence, class CompletionCondition> size_t read(SyncReadStream& stream, const MutableBufferSequence& buffers, CompletionCondition completion_condition, error_code& ec); template<class SyncReadStream, class DynamicBufferSequence> size_t read(SyncReadStream& stream, DynamicBufferSequence&& b); template<class SyncReadStream, class DynamicBufferSequence> size_t read(SyncReadStream& stream, DynamicBufferSequence&& b, error_code& ec); template<class SyncReadStream, class DynamicBufferSequence, class CompletionCondition> size_t read(SyncReadStream& stream, DynamicBufferSequence&& b, CompletionCondition completion_condition); template<class SyncReadStream, class DynamicBufferSequence, class CompletionCondition> size_t read(SyncReadStream& stream, DynamicBufferSequence&& b, CompletionCondition completion_condition, error_code& ec); // asynchronous read operations: template<class AsyncReadStream, class MutableBufferSequence, class CompletionToken> auto async_read(AsyncReadStream& stream, const MutableBufferSequence& buffers, CompletionToken&& token); template<class AsyncReadStream, class MutableBufferSequence, class CompletionCondition, class CompletionToken> auto async_read(AsyncReadStream& stream, const MutableBufferSequence& buffers, CompletionCondition completion_condition, CompletionToken&& token); template<class AsyncReadStream, class DynamicBufferSequence, class CompletionToken> auto async_read(AsyncReadStream& stream, DynamicBufferSequence&& b, CompletionToken&& token); template<class AsyncReadStream, class DynamicBufferSequence, class CompletionCondition, class CompletionToken> auto async_read(AsyncReadStream& stream, DynamicBufferSequence&& b, CompletionCondition completion_condition, CompletionToken&& token); // synchronous write operations: template<class SyncWriteStream, class ConstBufferSequence> size_t write(SyncWriteStream& stream, const ConstBufferSequence& buffers); template<class SyncWriteStream, class ConstBufferSequence> size_t write(SyncWriteStream& stream, const ConstBufferSequence& buffers, error_code& ec); template<class SyncWriteStream, class ConstBufferSequence, class CompletionCondition> size_t write(SyncWriteStream& stream, const ConstBufferSequence& buffers, CompletionCondition completion_condition); template<class SyncWriteStream, class ConstBufferSequence, class CompletionCondition> size_t write(SyncWriteStream& stream, const ConstBufferSequence& buffers, CompletionCondition completion_condition, error_code& ec); template<class SyncWriteStream, class DynamicBufferSequence> size_t write(SyncWriteStream& stream, DynamicBufferSequence&& b); template<class SyncWriteStream, class DynamicBufferSequence> size_t write(SyncWriteStream& stream, DynamicBufferSequence&& b, error_code& ec); template<class SyncWriteStream, class DynamicBufferSequence, class CompletionCondition> size_t write(SyncWriteStream& stream, DynamicBufferSequence&& b, CompletionCondition completion_condition); template<class SyncWriteStream, class DynamicBufferSequence, class CompletionCondition> size_t write(SyncWriteStream& stream, DynamicBufferSequence&& b, CompletionCondition completion_condition, error_code& ec); // asynchronous write operations: template<class AsyncWriteStream, class ConstBufferSequence, class CompletionToken> auto async_write(AsyncWriteStream& stream, const ConstBufferSequence& buffers, CompletionToken&& token); template<class AsyncWriteStream, class ConstBufferSequence, class CompletionCondition, class CompletionToken> auto async_write(AsyncWriteStream& stream, const ConstBufferSequence& buffers, CompletionCondition completion_condition, CompletionToken&& token); template<class AsyncWriteStream, class DynamicBufferSequence, class CompletionToken> auto async_write(AsyncWriteStream& stream, DynamicBufferSequence&& b, CompletionToken&& token); template<class AsyncWriteStream, class DynamicBufferSequence, class CompletionCondition, class CompletionToken> auto async_write(AsyncWriteStream& stream, DynamicBufferSequence&& b, CompletionCondition completion_condition, CompletionToken&& token); // synchronous delimited read operations: template<class SyncReadStream, class DynamicBufferSequence> size_t read_until(SyncReadStream& s, DynamicBufferSequence&& b, char delim); template<class SyncReadStream, class DynamicBufferSequence> size_t read_until(SyncReadStream& s, DynamicBufferSequence&& b, char delim, error_code& ec); template<class SyncReadStream, class DynamicBufferSequence> size_t read_until(SyncReadStream& s, DynamicBufferSequence&& b, const string_view& delim); template<class SyncReadStream, class DynamicBufferSequence> size_t read_until(SyncReadStream& s, DynamicBufferSequence&& b, const string_view& delim, error_code& ec); // asynchronous delimited read operations: template<class AsyncReadStream, class DynamicBufferSequence, class CompletionToken> auto async_read_until(AsyncReadStream& s, DynamicBufferSequence&& b, char delim, CompletionToken&& token); template<class AsyncReadStream, class DynamicBufferSequence, class CompletionToken> auto async_read_until(AsyncReadStream& s, DynamicBufferSequence&& b, const string_view& delim, CompletionToken&& token); } // inline namespace network_v1 } // namespace experimental template<> struct is_error_code_enum< experimental::network_v1::stream_errc> : public true_type {}; } // namespace std
A type that meets the requirements for convertibility to a mutable buffer
must meet the requirements of CopyConstructible
types (C++ Std, 20.1.3), and the requirements of Assignable
types (C++ Std, 23.1).
In the table below, X
denotes a class meeting the requirements for convertibility to a mutable
buffer, a
and b
denote values of type X
, and u
,
v
and w
denote identifiers.
Table 9. ConvertibleToMutableBuffer requirements
expression |
postcondition |
---|---|
mutable_buffer u(a); mutable_buffer v(a);
|
buffer_cast<void*>(u) == buffer_cast<void*>(v) && buffer_size(u) == buffer_size(v)
|
mutable_buffer u(a); mutable_buffer v = a;
|
buffer_cast<void*>(u) == buffer_cast<void*>(v) && buffer_size(u) == buffer_size(v)
|
mutable_buffer u(a); mutable_buffer v; v = a;
|
buffer_cast<void*>(u) == buffer_cast<void*>(v) && buffer_size(u) == buffer_size(v)
|
mutable_buffer u(a); const X& v = a; mutable_buffer w(v);
|
buffer_cast<void*>(u) == buffer_cast<void*>(w) && buffer_size(u) == buffer_size(w)
|
mutable_buffer u(a); X v(a); mutable_buffer w(v);
|
buffer_cast<void*>(u) == buffer_cast<void*>(w) && buffer_size(u) == buffer_size(w)
|
mutable_buffer u(a); X v = a; mutable_buffer w(v);
|
buffer_cast<void*>(u) == buffer_cast<void*>(w) && buffer_size(u) == buffer_size(w)
|
mutable_buffer u(a); X v(b); v = a; mutable_buffer w(v);
|
buffer_cast<void*>(u) == buffer_cast<void*>(w) && buffer_size(u) == buffer_size(w)
|
In the table below, X
denotes a class containing objects of type T
,
a
denotes a value of
type X
and u
denotes an identifier.
Table 10. MutableBufferSequence requirements
expression |
return type |
assertion/note |
---|---|---|
|
|
|
|
iterator type pointing to |
|
X(a); X u(a);
|
post: equal(begin(), end(), a.begin(), a.end(), [](const typename X::value_type& v1, const typename X::value_type& v2) { mutable_buffer b1(v1); mutable_buffer b2(v2); return buffer_cast<void*>(b1) == buffer_cast<void*>(b2) && buffer_size(b1) == buffer_size(b2); });
| |
|
|
note: the destructor is applied to every element of |
|
| |
|
|
A type that meets the requirements for convertibility to a const buffer
must meet the requirements of CopyConstructible
types (C++ Std, 20.1.3), and the requirements of Assignable
types (C++ Std, 23.1).
In the table below, X
denotes a class meeting the requirements for convertibility to a const
buffer, a
and b
denote values of type X
, and u
,
v
and w
denote identifiers.
Table 11. ConvertibleToConstBuffer requirements
expression |
postcondition |
---|---|
const_buffer u(a); const_buffer v(a);
|
buffer_cast<const void*>(u) == buffer_cast<const void*>(v) && buffer_size(u) == buffer_size(v)
|
const_buffer u(a); const_buffer v = a;
|
buffer_cast<const void*>(u) == buffer_cast<const void*>(v) && buffer_size(u) == buffer_size(v)
|
const_buffer u(a); const_buffer v; v = a;
|
buffer_cast<const void*>(u) == buffer_cast<const void*>(v) && buffer_size(u) == buffer_size(v)
|
const_buffer u(a); const X& v = a; const_buffer w(v);
|
buffer_cast<const void*>(u) == buffer_cast<const void*>(w) && buffer_size(u) == buffer_size(w)
|
const_buffer u(a); X v(a); const_buffer w(v);
|
buffer_cast<const void*>(u) == buffer_cast<const void*>(w) && buffer_size(u) == buffer_size(w)
|
const_buffer u(a); X v = a; const_buffer w(v);
|
buffer_cast<const void*>(u) == buffer_cast<const void*>(w) && buffer_size(u) == buffer_size(w)
|
const_buffer u(a); X v(b); v = a; const_buffer w(v);
|
buffer_cast<const void*>(u) == buffer_cast<const void*>(w) && buffer_size(u) == buffer_size(w)
|
In the table below, X
denotes a class containing objects of type T
,
a
denotes a value of
type X
and u
denotes an identifier.
Table 12. ConstBufferSequence requirements
expression |
return type |
assertion/note |
---|---|---|
|
|
|
|
iterator type pointing to |
|
X(a); X u(a);
|
post: equal(begin(), end(), a.begin(), a.end(), [](const typename X::value_type& v1, const typename X::value_type& v2) { const_buffer b1(v1); const_buffer b2(v2); return buffer_cast<const void*>(b1) == buffer_cast<const void*>(b2) && buffer_size(b1) == buffer_size(b2); });
| |
|
|
note: the destructor is applied to every element of |
|
| |
|
|
A dynamic buffer sequence encapsulates memory storage that may be automatically
resized as required, where the memory is divided into an input sequence
followed by an output sequence. These memory regions are internal to
the dynamic buffer sequence, but direct access to the elements is provided
to permit them to be efficiently used with I/O operations, such as the
send
or receive
operations of a socket. Data
written to the output sequence of a dynamic buffer sequence object is
appended to the input sequence of the same object.
A dynamic buffer sequence type X
shall satisfy the requirements of MoveConstructible
(C++ Std, [moveconstructible]) types in addition to those listed below.
In the table below, X
denotes a dynamic buffer sequence class, x
denotes a value of type X&
, x1
denotes values of type const X&
,
and n
denotes a value
of type size_t
, and
u
denotes an identifier.
Table 13. DynamicBufferSequence requirements
expression |
type |
assertion/note |
---|---|---|
|
type meeting ConstBufferSequence requirements. |
This type represents the memory associated with the input sequence. |
|
type meeting MutableBufferSequence requirements. |
This type represents the memory associated with the output sequence. |
|
|
Returns the size, in bytes, of the input sequence. |
|
|
Returns the permitted maximum of the sum of the sizes of the input sequence and output sequence. |
|
|
Returns the maximum sum of the sizes of the input sequence and output sequence that the dynamic buffer sequence can hold without requiring reallocation. |
|
|
Returns a constant buffer sequence |
|
|
Requires: |
|
Appends | |
|
Removes |
In this clause, a synchronous read operation is a function that reads data into a mutable buffer sequence argument of a type meeting MutableBufferSequence requirements.
The mutable buffer sequence specifies memory where the data should be placed. A synchronous read operation shall always fill a buffer in the sequence completely before proceeding to the next.
In this clause, an asynchronous read operation is an asynchronous operation that reads data into a mutable buffer sequence argument of a type meeting MutableBufferSequence requirements.
The mutable buffer sequence specifies memory where the data should be placed. An asynchronous read operation shall always fill a buffer in the sequence completely before proceeding to the next.
The read operation's implementation shall maintain one or more copies of the buffer sequence until such time as the read operation no longer requires access to the memory specified by the buffers in the sequence. The program must ensure the memory is valid until:
— the last copy of the buffer sequence is destroyed, or
— the handler for the asynchronous operation is invoked,
whichever comes first.
In this clause, a synchronous write operation is a function that writes data from a constant buffer sequence argument of a type meeting ConstBufferSequence requirements.
The constant buffer sequence specifies memory where the data to be written is located. A synchronous write operation shall always write a buffer in the sequence completely before proceeding to the next.
In this clause, an asynchronous write operation is an asynchronous operation that writes data from a constant buffer sequence argument of a type meeting ConstBufferSequence requirements.
The constant buffer sequence specifies memory where the data to be written is located. An asynchronous write operation shall always write a buffer in the sequence completely before proceeding to the next.
The write operation's implementation shall maintain one or more copies of the buffer sequence until such time as the write operation no longer requires access to the memory specified by the buffers in the sequence. The program must ensure the memory is valid until:
— the last copy of the buffer sequence is destroyed, or
— the handler for the asynchronous operation is invoked,
whichever comes first.
In the table below, a
denotes a synchronous read stream object, mb
denotes an object satisfying mutable
buffer sequence requirements, and ec
denotes an object of type error_code
.
Table 14. Buffer-oriented synchronous read stream requirements
operation |
type |
semantics, pre/post-conditions |
---|---|---|
|
|
Equivalent to: error_code ec; size_t s = a.read_some(mb, ec); if (ec) throw system_error(ec, __func__); return s;
|
|
|
Meets the requirements for a synchronous
read operation. |
In the table below, a
denotes an asynchronous read stream object, mb
denotes an object satisfying mutable
buffer sequence requirements, and t
is a completion token.
Table 15. Buffer-oriented asynchronous read stream requirements
operation |
type |
semantics, pre/post-conditions |
---|---|---|
|
A type satisfying the Executor requirements. |
Returns the associated I/O executor. |
|
The return type is determined according to the requirements for an asynchronous operation. |
Meets the requirements for an asynchronous
read operation with completion signature |
In the table below, a
denotes a synchronous write stream object, cb
denotes an object satisfying constant
buffer sequence requirements, and ec
denotes an object of type error_code
.
Table 16. Buffer-oriented synchronous write stream requirements
operation |
type |
semantics, pre/post-conditions |
---|---|---|
|
|
Equivalent to: error_code ec; size_t s = a.write_some(cb, ec); if (ec) throw system_error(ec, __func__); return s;
|
|
|
Meets the requirements for a synchronous
write operation. |
In the table below, a
denotes an asynchronous write stream object, cb
denotes an object satisfying constant
buffer sequence requirements, and t
is a completion token.
Table 17. Buffer-oriented asynchronous write stream requirements
operation |
type |
semantics, pre/post-conditions |
---|---|---|
|
A type satisfying the Executor requirements. |
Returns the associated I/O executor. |
|
The return type is determined according to the requirements for an asynchronous operation. |
Meets the requirements for an asynchronous
write operation with completion signature |
The mutable_buffer
class
meets the requirements for ConvertibleToMutableBuffer
and
ConvertibleToConstBuffer
.
namespace std { namespace experimental { inline namespace network_v1 { class mutable_buffer { public: // constructors: mutable_buffer() noexcept; mutable_buffer(void* p, size_t n) noexcept; private: void* data_; // exposition only size_t size_; // exposition only }; } // inline namespace network_v1 } // namespace experimental } // namespace std
The const_buffer
class
meets the requirements for ConvertibleToConstBuffer
.
namespace std { namespace experimental { inline namespace network_v1 { class const_buffer { public: // constructors: const_buffer() noexcept; const_buffer(const void* p, size_t n) noexcept; const_buffer(const mutable_buffer& b) noexcept; private: const void* data_; // exposition only size_t size_; // exposition only }; } // inline namespace network_v1 } // namespace experimental } // namespace std
The mutable_buffers_1
class
meets the requirements for MutableBufferSequence
, ConstBufferSequence
, ConvertibleToMutableBuffer
, and
ConvertibleToConstBuffer
.
namespace std { namespace experimental { inline namespace network_v1 { class mutable_buffers_1 : public mutable_buffer { public: // types: typedef mutable_buffer value_type; typedef unspecified const_iterator; // constructors: mutable_buffers_1(void* p, size_t n) noexcept; explicit mutable_buffers_1(const mutable_buffer& b) noexcept; // members: const_iterator begin() const noexcept; const_iterator end() const noexcept; }; } // inline namespace network_v1 } // namespace experimental } // namespace std
An object of class mutable_buffers_1
represents a sequence of exactly one mutable_buffer
object.
mutable_buffers_1(const void* p, size_t n) noexcept;
Effects: Constructs an object of class
mutable_buffers_1
, initializing the base class withmutable_buffer(p, n)
.
explicit mutable_buffers_1(const mutable_buffer& b) noexcept;
Effects: Constructs an object of class
mutable_buffers_1
, initializing the base class withmutable_buffer(b)
.
The const_buffers_1
class
meets the requirements for ConstBufferSequence
, and ConvertibleToConstBuffer
.
namespace std { namespace experimental { inline namespace network_v1 { class const_buffers_1 : public const_buffer { public: // types: typedef const_buffer value_type; typedef unspecified const_iterator; // constructors: const_buffers_1(const void* p, size_t n) noexcept; explicit const_buffers_1(const const_buffer& b) noexcept; // members: const_iterator begin() const noexcept; const_iterator end() const noexcept; }; } // inline namespace network_v1 } // namespace experimental } // namespace std
An object of class const_buffers_1
represents a sequence of exactly one const_buffer
object.
const_buffers_1(const void* p, size_t n) noexcept;
Effects: Constructs an object of class
const_buffers_1
, initializing the base class withconst_buffer(p, n)
.
explicit const_buffers_1(const const_buffer& b) noexcept;
Effects: Constructs an object of class
const_buffers_1
, initializing the base class withconst_buffer(b)
.
namespace std { namespace experimental { inline namespace network_v1 { template<class T> is_mutable_buffer_sequence; template<class T> is_const_buffer_sequence; template<class T> is_dynamic_buffer_sequence; } // inline namespace network_v1 } // namespace experimental } // namespace std
This sub-clause contains templates that may be used to query the properties
of a type at compile time. Each of these templates shall be a UnaryTypeTrait
(C++ Std, [meta.rqmts]) with a BaseCharacteristic of true_type
if the corresponding condition is true, otherwise false_type
.
Table 18. Buffer type traits
Template |
Condition |
Preconditions |
---|---|---|
|
|
|
|
|
|
|
|
|
template<class T> T buffer_cast(const mutable_buffer& b) noexcept; template<class T> T buffer_cast(const const_buffer& b) noexcept;
Returns:
static_cast<T>(b.data_)
.
size_t buffer_size(const mutable_buffer& b) noexcept; size_t buffer_size(const const_buffer& b) noexcept;
Returns:
b.size_
.
template<class ConstBufferSequence> size_t buffer_size(const ConstBufferSequence& buffers) noexcept;
Returns: The total size of all buffers in the sequence, as if computed as follows:
size_t total_size = 0; for (const auto& v: buffers) { const_buffer b(v); total_size += b.size_; } return total_size;
Remarks: This function overload shall not participate in overload resolution unless
is_const_buffer_sequence<ConstBufferSequence>::value
is true.
size_t buffer_copy(const mutable_buffer& dest, const const_buffer& source) noexcept; size_t buffer_copy(const mutable_buffer& dest, const const_buffer& source, size_t max_size) noexcept; template<class ConstBufferSequence> size_t buffer_copy(const mutable_buffer& dest, const ConstBufferSequence& source) noexcept; template<class ConstBufferSequence> size_t buffer_copy(const mutable_buffer& dest, const ConstBufferSequence& source, size_t max_size) noexcept; template<class MutableBufferSequence> size_t buffer_copy(const MutableBufferSequence& dest, const const_buffer& source) noexcept; template<class MutableBufferSequence> size_t buffer_copy(const MutableBufferSequence& dest, const const_buffer& source, size_t max_size) noexcept; template<class MutableBufferSequence, class ConstBufferSequence> size_t buffer_copy(const MutableBufferSequence& dest, const ConstBufferSequence& source) noexcept; template<class MutableBufferSequence, class ConstBufferSequence> size_t buffer_copy(const MutableBufferSequence& dest, const ConstBufferSequence& source, max_size) noexcept;
Effects: Copies bytes from the buffer or buffer sequence
source
to the buffer or buffer sequencedest
, as if by calls tomemcpy
.
The number of bytes copied is the lesser of:
—buffer_size(dest)
;
—buffer_size(source)
; and
—max_size
, if specified.
The mutable buffer or mutable buffer sequence
dest
specifies memory where the data should be placed. The operation shall always fill a buffer in the sequence completely before proceeding to the next.
The constant buffer or constant buffer sequence
source
specifies memory where the data to be written is located. The operation shall always copy a buffer in the sequence completely before proceeding to the next.
Returns: The number of bytes copied from
source
todest
.
Remarks: Where an overload accepts a template parameter
MutableBufferSequence
, the overload shall not participate in overload resolution unlessis_mutable_buffer_sequence<MutableBufferSequence>::value
is true. Where an overload accepts a template parameterConstBufferSequence
, the overload shall not participate in overload resolution unlessis_const_buffer_sequence<ConstBufferSequence>::value
is true.
mutable_buffer operator+(const mutable_buffer& b, size_t n) noexcept; mutable_buffer operator+(size_t n, const mutable_buffer& b) noexcept;
Returns: A
mutable_buffer
equivalent tomutable_buffer( buffer_cast<char*>(b) + min(n, buffer_size(b)), buffer_size(b) - min(n, buffer_size(b)));
const_buffer operator+(const const_buffer& b, size_t n) noexcept; const_buffer operator+(size_t n, const const_buffer& b) noexcept;
Returns: A
const_buffer
equivalent toconst_buffer( buffer_cast<const char*>(b) + min(n, buffer_size(b)), buffer_size(b) - min(n, buffer_size(b)));
mutable_buffers_1 operator+(const mutable_buffers_1& b, size_t n) noexcept; mutable_buffers_1 operator+(size_t n, const mutable_buffers_1& b) noexcept;
Returns: A
mutable_buffers_1
equivalent tomutable_buffers_1( buffer_cast<char*>(b) + min(n, buffer_size(b)), buffer_size(b) - min(n, buffer_size(b)));
const_buffers_1 operator+(const const_buffers_1& b, size_t n) noexcept; const_buffers_1 operator+(size_t n, const const_buffers_1& b) noexcept;
Returns: A
const_buffers_1
equivalent toconst_buffers_1( buffer_cast<const char*>(b) + min(n, buffer_size(b)), buffer_size(b) - min(n, buffer_size(b)));
In the functions below, T
must be a POD type.
For the function overloads below that accept an argument of type vector<>
,
the buffer objects returned are invalidated by any vector operation that
also invalidates all references, pointers and iterators referring to the
elements in the sequence (C++ Std, [vector]).
For the function overloads below that accept an argument of type basic_string<>
,
the buffer objects returned are invalidated according to the rules defined
for invalidation of references, pointers and iterators referring to elements
of the sequence (C++ Std, [string.require]).
mutable_buffers_1 buffer(void* p, size_t n) noexcept;
Returns:
mutable_buffers_1(p, n)
.
const_buffers_1 buffer(const void* p, size_t n) noexcept;
Returns:
const_buffers_1(p, n)
.
mutable_buffers_1 buffer(const mutable_buffer& b) noexcept;
Returns:
mutable_buffers_1(b)
.
mutable_buffers_1 buffer(const mutable_buffer& b, size_t n) noexcept;
Returns: A
mutable_buffers_1
value equivalent to:mutable_buffers_1( buffer_cast<void*>(b), min(buffer_size(b), n));
const_buffers_1 buffer(const const_buffer& b) noexcept;
Returns:
const_buffers_1(b)
.
const_buffers_1 buffer(const const_buffer& b, size_t n) noexcept;
Returns: A
const_buffers_1
value equivalent to:const_buffers_1( buffer_cast<const void*>(b), min(buffer_size(b), n));
template<class T, size_t N> mutable_buffers_1 buffer(T (&arr)[N]) noexcept;
Returns: A
mutable_buffers_1
value equivalent to:mutable_buffers_1( static_cast<void*>(arr), N * sizeof(T));
template<class T, size_t N> mutable_buffers_1 buffer(T (&arr)[N], size_t n) noexcept;
Returns: A
mutable_buffers_1
value equivalent to:mutable_buffers_1( static_cast<void*>(arr), min(N * sizeof(T), n));
template<class T, size_t N> const_buffers_1 buffer(const T (&arr)[N]) noexcept;
Returns: A
const_buffers_1
value equivalent to:const_buffers_1( static_cast<const void*>(arr), N * sizeof(T));
template<class T, size_t N> const_buffers_1 buffer(const T (&arr)[N], size_t n) noexcept;
Returns: A
const_buffers_1
value equivalent to:const_buffers_1( static_cast<const void*>(arr), min(N * sizeof(T), n));
template<class T, size_t N> mutable_buffers_1 buffer(array<T, N>& arr) noexcept;
Returns: A
mutable_buffers_1
value equivalent to:mutable_buffers_1( arr.data(), arr.size() * sizeof(T));
template<class T, size_t N> mutable_buffers_1 buffer(array<T, N>& arr, size_t n) noexcept;
Returns: A
mutable_buffers_1
value equivalent to:mutable_buffers_1( arr.data(), min(arr.size() * sizeof(T), n));
template<class T, size_t N> const_buffers_1 buffer(array<const T, N>& arr) noexcept;
Returns: A
const_buffers_1
value equivalent to:const_buffers_1( arr.data(), arr.size() * sizeof(T));
template<class T, size_t N> const_buffers_1 buffer(array<const T, N>& arr, size_t n) noexcept;
Returns: A
const_buffers_1
value equivalent to:const_buffers_1( arr.data(), min(arr.size() * sizeof(T), n));
template<class T, size_t N> const_buffers_1 buffer(const array<T, N>& arr) noexcept;
Returns: A
const_buffers_1
value equivalent to:const_buffers_1( arr.data(), arr.size() * sizeof(T));
template<class T, size_t N> const_buffers_1 buffer(const array<T, N>& arr, size_t n) noexcept;
Returns: A
const_buffers_1
value equivalent to:const_buffers_1( arr.data(), min(arr.size() * sizeof(T), n));
template<class T, class Allocator> mutable_buffers_1 buffer(vector<T, Allocator>& vec) noexcept;
Returns: A
mutable_buffers_1
value equivalent to:mutable_buffers_1( vec.size() ? &vec[0] : nullptr, vec.size() * sizeof(T));
template<class T, class Allocator> mutable_buffers_1 buffer(vector<T, Allocator>& vec, size_t n) noexcept;
Returns: A
mutable_buffers_1
value equivalent to:mutable_buffers_1( vec.size() ? &vec[0] : nullptr, min(vec.size() * sizeof(T), n));
template<class T, class Allocator> const_buffers_1 buffer(const vector<T, Allocator>& vec) noexcept;
Returns: A
const_buffers_1
value equivalent to:const_buffers_1( vec.size() ? &vec[0] : nullptr, vec.size() * sizeof(T));
template<class T, class Allocator> const_buffers_1 buffer(const vector<T, Allocator>& vec, size_t n) noexcept;
Returns: A
const_buffers_1
value equivalent to:const_buffers_1( vec.size() ? &vec[0] : nullptr, min(vec.size() * sizeof(T), n));
template<class CharT, class Traits, class Allocator> mutable_buffers_1 buffer(basic_string<CharT, Traits, Allocator>& str) noexcept;
Returns: A
mutable_buffers_1
value equivalent to:mutable_buffers_1( str.size() ? &str[0] : nullptr, str.size() * sizeof(CharT));
template<class CharT, class Traits, class Allocator> mutable_buffers_1 buffer(basic_string<CharT, Traits, Allocator>& str, size_t n) noexcept;
Returns: A
mutable_buffers_1
value equivalent to:mutable_buffers_1( str.size() ? &str[0] : nullptr, min(str.size() * sizeof(CharT), n));
template<class CharT, class Traits, class Allocator> const_buffers_1 buffer(const basic_string<CharT, Traits, Allocator>& str) noexcept;
Returns: A
const_buffers_1
value equivalent to:const_buffers_1( str.data() str.size() * sizeof(CharT));
template<class CharT, class Traits, class Allocator> const_buffers_1 buffer(const basic_string<CharT, Traits, Allocator>& str, size_t n) noexcept;
Returns: A
const_buffers_1
value equivalent to:const_buffers_1( str.data() min(str.size() * sizeof(CharT), n));
template<class CharT, class Traits> const_buffers_1 buffer(const basic_string_view<CharT, Traits>& str) noexcept;
Returns: A
const_buffers_1
value equivalent to:const_buffers_1( str.data() str.size() * sizeof(CharT));
template<class CharT, class Traits> const_buffers_1 buffer(const basic_string_view<CharT, Traits>& str, size_t n) noexcept;
Returns: A
const_buffers_1
value equivalent to:const_buffers_1( str.data() min(str.size() * sizeof(CharT), n));
The dynamic_vector_buffer
class template meets the requirements for DynamicBufferSequence
.
namespace std { namespace experimental { inline namespace network_v1 { template<class T, class Allocator> class dynamic_vector_buffer { public: // types: typedef const_buffers_1 const_buffers_type; typedef mutable_buffers_1 mutable_buffers_type; // constructors: explicit dynamic_vector_buffer(vector<T, Allocator>& vec) noexcept; dynamic_vector_buffer(vector<T, Allocator>& vec, size_t maximum_size) noexcept; dynamic_vector_buffer(dynamic_vector_buffer&&) = default; // members: size_t size() const noexcept; size_t max_size() const noexcept; size_t capacity() const noexcept; const_buffers_type data() const noexcept; mutable_buffers_type prepare(size_t n); void commit(size_t n); void consume(size_t n); private: vector<T, Allocator>& vec_; // exposition only size_t size_; // exposition only const size_t max_size_; // exposition only }; } // inline namespace network_v1 } // namespace experimental } // namespace std
The dynamic_vector_buffer
class template requires that T
is a POD type and that sizeof(T)
== 1
.
explicit dynamic_vector_buffer(vector<T, Allocator>& vec) noexcept;
Effects: Constructs an object of type
dynamic_vector_buffer
, bindingvec_
tovec
, initializingsize_
withvec.size()
, and initializingmax_size_
withvec.max_size()
.
dynamic_vector_buffer(vector<T, Allocator>& vec, size_t maximum_size) noexcept;
Requires:
vec.size() <= maximum_size
.
Effects: Constructs an object of type
dynamic_vector_buffer
, bindingvec_
tovec
, initializingsize_
withvec.size()
, and initializingmax_size_
withmaximum_size
.
size_t size() const noexcept;
Returns:
size_
.
size_t max_size() const noexcept;
Returns:
max_size_
.
size_t capacity() const noexcept;
Returns:
vec_.capacity()
.
const_buffers_type data() const noexcept;
Returns:
buffer(vec_, size_)
.
mutable_buffers_type prepare(size_t n);
Requires:
size() + n <= max_size()
.
Effects: Performs
str.resize(size_ + n)
.
Returns:
buffer(buffer(vec_) + size_, n)
.
Throws:
length_error
ifsize() + n > max_size()
.
void commit(size_t n);
Effects: Performs:
size_ += min(n, vec_.size() - size_); vec_.resize(size_);
void consume(size_t n);
Effects: Performs:
size_t m = min(n, size_); vec_.erase(vec_.begin(), vec_.begin() + m); size_ -= m;
The dynamic_string_buffer
class template meets the requirements for DynamicBufferSequence
.
namespace std { namespace experimental { inline namespace network_v1 { template<class CharT, class Traits, class Allocator> class dynamic_string_buffer { public: // types: typedef const_buffers_1 const_buffers_type; typedef mutable_buffers_1 mutable_buffers_type; // constructors: explicit dynamic_string_buffer(basic_string<CharT, Traits, Allocator>& str) noexcept; dynamic_string_buffer(basic_string<CharT, Traits, Allocator>& str, size_t maximum_size) noexcept; dynamic_string_buffer(dynamic_string_buffer&&) = default; // members: size_t size() const noexcept; size_t max_size() const noexcept; size_t capacity() const noexcept; const_buffers_type data() const noexcept; mutable_buffers_type prepare(size_t n); void commit(size_t n) noexcept; void consume(size_t n); private: basic_string<CharT, Traits, Allocator>& str_; // exposition only size_t size_; // exposition only const size_t max_size_; // exposition only }; } // inline namespace network_v1 } // namespace experimental } // namespace std
The dynamic_string_buffer
class template requires that sizeof(CharT) == 1
.
explicit dynamic_string_buffer(basic_string<CharT, Traits, Allocator>& str) noexcept;
Effects: Constructs an object of type
dynamic_string_buffer
, bindingstr_
tostr
, initializingsize_
withstr.size()
, and initializingmax_size_
withstr.max_size()
.
dynamic_string_buffer(basic_string<CharT, Traits, Allocator>& str, size_t maximum_size) noexcept;
Requires:
str.size() <= maximum_size
.
Effects: Constructs an object of type
dynamic_string_buffer
, bindingstr_
tostr
, initializingsize_
withstr.size()
, and initializingmax_size_
withmaximum_size
.
size_t size() const noexcept;
Returns:
size_
.
size_t max_size() const noexcept;
Returns:
max_size_
.
size_t capacity() const noexcept;
Returns:
str_.capacity()
.
const_buffers_type data() const noexcept;
Returns:
buffer(str_, size_)
.
mutable_buffers_type prepare(size_t n);
Requires:
size() + n <= max_size()
.
Effects: Performs
str.resize(size_ + n)
.
Returns:
buffer(buffer(str_) + size_, n)
.
Throws:
length_error
ifsize() + n > max_size()
.
void commit(size_t n) noexcept;
Effects: Performs:
size_ += min(n, str_.size() - size_); str_.resize(size_);
void consume(size_t n);
Effects: Performs:
size_t m = min(n, size_); str_.erase(m); size_ -= m;
template<class T, class Allocator> dynamic_vector_buffer<T, Allocator> dynamic_buffer(vector<T, Allocator>& vec) noexcept;
Requires:
T
is a POD type andsizeof(T) == 1
.
Returns:
dynamic_vector_buffer<T, Allocator>(vec)
.
template<class T, class Allocator> dynamic_vector_buffer<T, Allocator> dynamic_buffer(vector<T, Allocator>& vec, size_t n) noexcept;
Requires:
T
is a POD type andsizeof(T) == 1
.
Returns:
dynamic_vector_buffer<T, Allocator>(vec, n)
.
template<class CharT, class Traits, class Allocator> dynamic_string_buffer<CharT, Traits, Allocator> dynamic_buffer(basic_string<CharT, Traits, Allocator>& str) noexcept;
Requires:
sizeof(CharT) == 1
.
Returns:
dynamic_string_buffer<CharT, Traits, Allocator>(str)
.
template<class CharT, class Traits, class Allocator> dynamic_string_buffer<CharT, Traits, Allocator> dynamic_buffer(basic_string<CharT, Traits, Allocator>& str, size_t n) noexcept;
Requires:
sizeof(CharT) == 1
.
Returns:
dynamic_string_buffer<CharT, Traits, Allocator>(str, n)
.
namespace std { namespace experimental { inline namespace network_v1 { class transfer_all { public: size_t operator()(const error_code& ec, size_t) const; }; } // inline namespace network_v1 } // namespace experimental } // namespace std
The class transfer_all
is a function object type for use as a CompletionCondition
argument to synchronous read, asynchronous read, synchronous
write, or asynchronous write
operations.
size_t operator()(const error_code& ec, size_t) const;
Returns: If
!ec
, an unspecified non-zero value. Otherwise0
.
namespace std { namespace experimental { inline namespace network_v1 { class transfer_at_least { public: explicit transfer_at_least(size_t m); size_t operator()(const error_code& ec, size_t s) const; private: size_t minimum_; // exposition only }; } // inline namespace network_v1 } // namespace experimental } // namespace std
The class transfer_at_least
is a function object type for use as a CompletionCondition
argument to synchronous read, asynchronous read, synchronous
write, or asynchronous write
operations.
explicit transfer_at_least(size_t m);
Postconditions:
minimum_ == m
.
size_t operator()(const error_code& ec, size_t n) const;
Returns: If
!ec && n < minimum_
, an unspecified non-zero value. Otherwise0
.
namespace std { namespace experimental { inline namespace network_v1 { class transfer_exactly { public: explicit transfer_exactly(size_t e); size_t operator()(const error_code& ec, size_t s) const; private: size_t exact_; // exposition only }; } // inline namespace network_v1 } // namespace experimental } // namespace std
The class transfer_exactly
is a function object type for use as a CompletionCondition
argument to synchronous read, asynchronous read, synchronous
write, or asynchronous write
operations.
explicit transfer_exactly(size_t e);
Postconditions:
exact_ == e
.
size_t operator()(const error_code& ec, size_t n) const;
Returns: If
!ec && n < exact_
, the result ofmin(exact_ - n, N)
, whereN
is an unspecified non-zero value. Otherwise0
.
template<class SyncReadStream, class MutableBufferSequence> size_t read(SyncReadStream& stream, const MutableBufferSequence& buffers); template<class SyncReadStream, class MutableBufferSequence> size_t read(SyncReadStream& stream, const MutableBufferSequence& buffers, error_code& ec); template<class SyncReadStream, class MutableBufferSequence, class CompletionCondition> size_t read(SyncReadStream& stream, const MutableBufferSequence& buffers, CompletionCondition completion_condition); template<class SyncReadStream, class MutableBufferSequence, class CompletionCondition> size_t read(SyncReadStream& stream, const MutableBufferSequence& buffers, CompletionCondition completion_condition, error_code& ec);
Effects: Reads data from the buffer-oriented synchronous read stream object
stream
by performing zero or more calls to the stream'sread_some
member function.
The
completion_condition
parameter specifies a function object to be called prior to each call to the stream'sread_some
member function. The function object is passed theerror_code
value from the most recentread_some
call, and the total number of bytes transferred in the synchronous read operation so far. The function object return value specifies the maximum number of bytes to be read on the subsequentread_some
call. Overloads where a completion condition is not specified behave as if called with an object of classtransfer_all
.
The synchronous read operation continues until:
— the total number of bytes transferred is equal to
buffer_size(buffers)
; or
— the completion condition returns
0
.
On return,
ec
contains theerror_code
value from the most recentread_some
call.
Returns: The total number of bytes transferred in the synchronous read operation.
Remarks: This function shall not participate in overload resolution unless
is_mutable_buffer_sequence<MutableBufferSequence>::value
is true.
template<class SyncReadStream, class DynamicBufferSequence> size_t read(SyncReadStream& stream, DynamicBufferSequence&& b); template<class SyncReadStream, class DynamicBufferSequence> size_t read(SyncReadStream& stream, DynamicBufferSequence&& b, error_code& ec); template<class SyncReadStream, class DynamicBufferSequence, class CompletionCondition> size_t read(SyncReadStream& stream, DynamicBufferSequence&& b, CompletionCondition completion_condition); template<class SyncReadStream, class DynamicBufferSequence, class CompletionCondition> size_t read(SyncReadStream& stream, DynamicBufferSequence&& b, CompletionCondition completion_condition, error_code& ec);
Effects: Reads data from the synchronous read stream object
stream
by performing zero or more calls to the stream'sread_some
member function.
Data is placed into the dynamic buffer sequence object
b
. A mutable buffer sequence is obtained prior to eachread_some
call usingb.prepare(N)
, whereN
is an unspecified value such thatN <= max_size() - size()
. [Note: Implementations are encouraged to useb.capacity()
when determiningN
, to minimize the number ofread_some
calls performed on the stream. —end note] After eachread_some
call, the implementation performsb.commit(n)
, wheren
is the return value fromread_some
.
The
completion_condition
parameter specifies a function object to be called prior to each call to the stream'sread_some
member function. The function object is passed theerror_code
value from the most recentread_some
call, and the total number of bytes transferred in the synchronous read operation so far. The function object return value specifies the maximum number of bytes to be read on the subsequentread_some
call. Overloads where a completion condition is not specified behave as if called with an object of classtransfer_all
.
The synchronous read operation continues until:
—
b.size() == b.max_size()
; or
— the completion condition returns
0
.
On return,
ec
contains theerror_code
value from the most recentread_some
call.
Returns: The total number of bytes transferred in the synchronous read operation.
Remarks: This function shall not participate in overload resolution unless
is_dynamic_buffer_sequence<DynamicBufferSequence>::value
is true.
template<class AsyncReadStream, class MutableBufferSequence, class CompletionToken> auto async_read(AsyncReadStream& stream, const MutableBufferSequence& buffers, CompletionToken&& token); template<class AsyncReadStream, class MutableBufferSequence, class CompletionCondition, class CompletionToken> auto async_read(AsyncReadStream& stream, const MutableBufferSequence& buffers, CompletionCondition completion_condition, CompletionToken&& token);
Completion signature:
void(error_code ec, size_t n)
.
Effects: Initiates an asynchronous operation to read data from the buffer-oriented asynchronous read stream object
stream
by performing zero or more asynchronous operations on the stream using the stream'sasync_read_some
member function (henceforth referred to as asynchronous read_some operations).
The
completion_condition
parameter specifies a function object to be called prior to each asynchronous read_some operation. The function object is passed theerror_code
value from the most recent asynchronous read_some operation, and the total number of bytes transferred in the asynchronous read operation so far. The function object return value specifies the maximum number of bytes to be read on the subsequent asynchronous read_some operation. Overloads where a completion condition is not specified behave as if called with an object of classtransfer_all
.
The asynchronous read operation continues until:
— the total number of bytes transferred is equal to
buffer_size(buffers)
; or
— the completion condition returns
0
.
The program must ensure the
AsyncReadStream
objectstream
is valid until the handler for the asynchronous operation is invoked.
On completion of the asynchronous operation,
ec
is theerror_code
value from the most recent asynchronous read_some operation, andn
is the total number of bytes transferred.
Remarks: This function shall not participate in overload resolution unless
is_mutable_buffer_sequence<MutableBufferSequence>::value
is true.
template<class AsyncReadStream, class DynamicBufferSequence, class CompletionToken> auto async_read(AsyncReadStream& stream, DynamicBufferSequence&& b, CompletionToken&& token); template<class AsyncReadStream, class DynamicBufferSequence, class CompletionCondition, class CompletionToken> auto async_read(AsyncReadStream& stream, DynamicBufferSequence&& b, CompletionCondition completion_condition, CompletionToken&& token);
Completion signature:
void(error_code ec, size_t n)
.
Effects: Initiates an asynchronous operation to read data from the buffer-oriented asynchronous read stream object
stream
by performing one or more asynchronous read_some operations on the stream.
Data is placed into the dynamic buffer sequence object
b
. A mutable buffer sequence is obtained prior to eachasync_read_some
call usingb.prepare(N)
, whereN
is an unspecified value such thatN <= max_size() - size()
. [Note: Implementations are encouraged to useb.capacity()
when determiningN
, to minimize the number of asynchronous read_some operations performed on the stream. —end note] After the completion of each asynchronous read_some operation, the implementation performsb.commit(n)
, wheren
is the value passed to the asynchronous read_some operation's completion handler.
The
completion_condition
parameter specifies a function object to be called prior to each asynchronous read_some operation. The function object is passed theerror_code
value from the most recent asynchronous read_some operation, and the total number of bytes transferred in the asynchronous read operation so far. The function object return value specifies the maximum number of bytes to be read on the subsequent asynchronous read_some operation. Overloads where a completion condition is not specified behave as if called with an object of classtransfer_all
.
The asynchronous read operation continues until:
—
b.size() == b.max_size()
; or
— the completion condition returns
0
.
The program must ensure both the
AsyncReadStream
objectstream
and the memory associated with the dynamic buffer sequenceb
are valid until the handler for the asynchronous operation is invoked.
On completion of the asynchronous operation,
ec
is theerror_code
value from the most recent asynchronous read_some operation, andn
is the total number of bytes transferred.
Remarks: This function shall not participate in overload resolution unless
is_dynamic_buffer_sequence<DynamicBufferSequence>::value
is true.
template<class SyncWriteStream, class ConstBufferSequence> size_t write(SyncWriteStream& stream, const ConstBufferSequence& buffers); template<class SyncWriteStream, class ConstBufferSequence> size_t write(SyncWriteStream& stream, const ConstBufferSequence& buffers, error_code& ec); template<class SyncWriteStream, class ConstBufferSequence, class CompletionCondition> size_t write(SyncWriteStream& stream, const ConstBufferSequence& buffers, CompletionCondition completion_condition); template<class SyncWriteStream, class ConstBufferSequence, class CompletionCondition> size_t write(SyncWriteStream& stream, const ConstBufferSequence& buffers, CompletionCondition completion_condition, error_code& ec);
Effects: Writes data to the buffer-oriented synchronous write stream object
stream
by performing zero or more calls to the stream'swrite_some
member function.
The
completion_condition
parameter specifies a function object to be called prior to each call to the stream'swrite_some
member function. The function object is passed theerror_code
value from the most recentwrite_some
call, and the total number of bytes transferred in the synchronous write operation so far. The function object return value specifies the maximum number of bytes to be write on the subsequentwrite_some
call. Overloads where a completion condition is not specified behave as if called with an object of classtransfer_all
.
The synchronous write operation continues until:
— the total number of bytes transferred is equal to
buffer_size(buffers)
; or
— the completion condition returns
0
.
On return,
ec
contains theerror_code
value from the most recentwrite_some
call.
Returns: The total number of bytes transferred in the synchronous write operation.
Remarks: This function shall not participate in overload resolution unless
is_const_buffer_sequence<ConstBufferSequence>::value
is true.
template<class SyncWriteStream, class DynamicBufferSequence> size_t write(SyncWriteStream& stream, DynamicBufferSequence&& b); template<class SyncWriteStream, class DynamicBufferSequence> size_t write(SyncWriteStream& stream, DynamicBufferSequence&& b, error_code& ec); template<class SyncWriteStream, class DynamicBufferSequence, class CompletionCondition> size_t write(SyncWriteStream& stream, DynamicBufferSequence&& b, CompletionCondition completion_condition); template<class SyncWriteStream, class DynamicBufferSequence, class CompletionCondition> size_t write(SyncWriteStream& stream, DynamicBufferSequence&& b, CompletionCondition completion_condition, error_code& ec);
Effects: Writes data to the synchronous write stream object
stream
by performing zero or more calls to the stream'swrite_some
member function.
Data is written from the dynamic buffer sequence object
b
. A constant buffer sequence is obtained usingb.data()
. After the data has been written to the stream, the implementation performsb.consume(n)
, wheren
is the number of bytes successfully written.
The
completion_condition
parameter specifies a function object to be called after each call to the stream'swrite_some
member function. The function object is passed theerror_code
value from the most recentwrite_some
call, and the total number of bytes transferred in the synchronous write operation so far. Overloads where a completion condition is not specified behave as if called with an object of classtransfer_all
.
The synchronous write operation continues until:
—
b.size() == 0
; or
— the completion condition returns
0
.
On return,
ec
contains theerror_code
value from the most recentwrite_some
call.
Returns: The total number of bytes transferred in the synchronous write operation.
Remarks: This function shall not participate in overload resolution unless
is_dynamic_buffer_sequence<DynamicBufferSequence>::value
is true.
template<class AsyncWriteStream, class ConstBufferSequence, class CompletionToken> auto async_write(AsyncWriteStream& stream, const ConstBufferSequence& buffers, CompletionToken&& token); template<class AsyncWriteStream, class ConstBufferSequence, class CompletionCondition, class CompletionToken> auto async_write(AsyncWriteStream& stream, const ConstBufferSequence& buffers, CompletionCondition completion_condition, CompletionToken&& token);
Completion signature:
void(error_code ec, size_t n)
.
Effects: Initiates an asynchronous operation to write data to the buffer-oriented asynchronous write stream object
stream
by performing zero or more asynchronous operations on the stream using the stream'sasync_write_some
member function (henceforth referred to as asynchronous write_some operations).
The
completion_condition
parameter specifies a function object to be called prior to each asynchronous write_some operation. The function object is passed theerror_code
value from the most recent asynchronous write_some operation, and the total number of bytes transferred in the asynchronous write operation so far. The function object return value specifies the maximum number of bytes to be write on the subsequent asynchronous write_some operation. Overloads where a completion condition is not specified behave as if called with an object of classtransfer_all
.
The asynchronous write operation continues until:
— the total number of bytes transferred is equal to
buffer_size(buffers)
; or
— the completion condition returns
0
.
The program must ensure the
AsyncWriteStream
objectstream
is valid until the handler for the asynchronous operation is invoked.
On completion of the asynchronous operation,
ec
is theerror_code
value from the most recent asynchronous write_some operation, andn
is the total number of bytes transferred.
Remarks: This function shall not participate in overload resolution unless
is_const_buffer_sequence<ConstBufferSequence>::value
is true.
template<class AsyncWriteStream, class DynamicBufferSequence, class CompletionToken> auto async_write(AsyncWriteStream& stream, DynamicBufferSequence&& b, CompletionToken&& token); template<class AsyncWriteStream, class DynamicBufferSequence, class CompletionCondition, class CompletionToken> auto async_write(AsyncWriteStream& stream, DynamicBufferSequence&& b, CompletionCondition completion_condition, CompletionToken&& token);
Completion signature:
void(error_code ec, size_t n)
.
Effects: Initiates an asynchronous operation to write data to the buffer-oriented asynchronous write stream object
stream
by performing zero or more asynchronous write_some operations on the stream.
Data is written from the dynamic buffer sequence object
b
. A constant buffer sequence is obtained usingb.data()
. After the data has been written to the stream, the implementation performsb.consume(n)
, wheren
is the number of bytes successfully written.
The
completion_condition
parameter specifies a function object to be called prior to each asynchronous write_some operation. The function object is passed theerror_code
value from the most recent asynchronous write_some operation, and the total number of bytes transferred in the asynchronous write operation so far. The function object return value specifies the maximum number of bytes to be write on the subsequent asynchronous write_some operation. Overloads where a completion condition is not specified behave as if called with an object of classtransfer_all
.
The asynchronous write operation continues until:
—
b.size() == 0
; or
— the completion condition returns
0
.
The program must ensure both the
AsyncWriteStream
objectstream
and the memory associated with the dynamic buffer sequenceb
are valid until the handler for the asynchronous operation is invoked.
On completion of the asynchronous operation,
ec
is theerror_code
value from the most recent asynchronous write_some operation, andn
is the total number of bytes transferred.
Remarks: This function shall not participate in overload resolution unless
is_dynamic_buffer_sequence<DynamicBufferSequence>::value
is true.
template<class SyncReadStream, class DynamicBufferSequence> size_t read_until(SyncReadStream& s, DynamicBufferSequence&& b, char delim); template<class SyncReadStream, class DynamicBufferSequence> size_t read_until(SyncReadStream& s, DynamicBufferSequence&& b, char delim, error_code& ec); template<class SyncReadStream, class DynamicBufferSequence> size_t read_until(SyncReadStream& s, DynamicBufferSequence&& b, const string_view& delim); template<class SyncReadStream, class DynamicBufferSequence> size_t read_until(SyncReadStream& s, DynamicBufferSequence&& b, const string_view& delim, error_code& ec);
Effects: Reads data from the buffer-oriented synchronous read stream object
stream
by performing zero or more calls to the stream'sread_some
member function, until the input sequence of the dynamic buffer sequence objectb
contains the specified delimiterdelim
.
Data is placed into the dynamic buffer sequence object
b
. A mutable buffer sequence is obtained prior to eachread_some
call usingb.prepare(N)
, whereN
is an unspecified value such thatN <= max_size() - size()
. [Note: Implementations are encouraged to useb.capacity()
when determiningN
, to minimize the number ofread_some
calls performed on the stream. —end note] After eachread_some
call, the implementation performsb.commit(n)
, wheren
is the return value fromread_some
.
The synchronous read_until operation continues until:
— the input sequence of
b
contains the delimiterdelim
; or
—
b.size() == b.max_size()
; or
— an synchronous read_some operation fails.
On exit, if the input sequence of
b
contains the delimiter,ec
is set such that!ec
is true. Otherwise, ifb.size() == b.max_size()
,ec
is set such thatec == stream_errc::not_found
. Ifb.size() < b.max_size()
,ec
contains theerror_code
from the most recentread_some
call.
Returns: The number of bytes in the input sequence of
b
up to and including the delimiter, if present. Otherwise returns0
.
template<class AsyncReadStream, class DynamicBufferSequence, class CompletionToken> auto async_read_until(AsyncReadStream& s, DynamicBufferSequence&& b, char delim, CompletionToken&& token); template<class AsyncReadStream, class DynamicBufferSequence, class CompletionToken> auto async_read_until(AsyncReadStream& s, DynamicBufferSequence&& b, const string_view& delim, CompletionToken&& token);
Completion signature:
void(error_code ec, size_t n)
.
Effects: Initiates an asynchronous operation to read data from the buffer-oriented asynchronous read stream object
stream
by performing zero or more asynchronous read_some operations on the stream, until the input sequence of the dynamic buffer sequence objectb
contains the specified delimiterdelim
.
Data is placed into the dynamic buffer sequence object
b
. A mutable buffer sequence is obtained prior to eachasync_read_some
call usingb.prepare(N)
, whereN
is an unspecified value such thatN <= max_size() - size()
. [Note: Implementations are encouraged to useb.capacity()
when determiningN
, to minimize the number of asynchronous read_some operations performed on the stream. —end note] After the completion of each asynchronous read_some operation, the implementation performsb.commit(n)
, wheren
is the value passed to the asynchronous read_some operation's completion handler.
The asynchronous read_until operation continues until:
— the input sequence of
b
contains the delimiterdelim
; or
—
b.size() == b.max_size()
; or
— an asynchronous read_some operation fails.
The program must ensure both the
AsyncReadStream
objectstream
and the memory associated with the dynamic buffer sequenceb
are valid until the handler for the asynchronous operation is invoked.
If
delim
is of typestring_view
, the implementation shall copy the underlying sequence of characters prior to initiating an asynchronous read_some operation on the stream. [Note: This means that the caller is not required to guarantee the validity of the delimiter string after the call toasync_read_until
returns. —end note]
On completion of the asynchronous operation, if the input sequence of
b
contains the delimiter,ec
is set such that!ec
is true. Otherwise, ifb.size() == b.max_size()
,ec
is set such thatec == stream_errc::not_found
. Ifb.size() < b.max_size()
,ec
contains theerror_code
from the most recent asynchronous read_some operation.n
shall contain the number of bytes in the input sequence ofb
up to and including the delimiter, if present, otherwise0
.
namespace std { namespace experimental { inline namespace network_v1 { enum class socket_errc { already_open = implementation defined, not_found = implementation defined }; const error_category& socket_category() noexcept; error_code make_error_code(socket_errc e) noexcept; error_condition make_error_condition(socket_errc e) noexcept; // Sockets: class socket_base; template<class Protocol> class basic_socket; template<class Protocol> class basic_datagram_socket; template<class Protocol> class basic_stream_socket; template<class Protocol> class basic_socket_acceptor; // Socket streams: template<class Protocol, class Clock = chrono::steady_clock, class WaitTraits = wait_traits<Clock>> class basic_socket_streambuf; template<class Protocol, class Clock = chrono::steady_clock, class WaitTraits = wait_traits<Clock>> class basic_socket_iostream; // synchronous connect operations: template<class Protocol, class InputIterator> InputIterator connect(basic_socket<Protocol>& s, InputIterator first); template<class Protocol, class InputIterator> InputIterator connect(basic_socket<Protocol>& s, InputIterator first, error_code& ec); template<class Protocol, class InputIterator> InputIterator connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last); template<class Protocol, class InputIterator> InputIterator connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last, error_code& ec); template<class Protocol, class InputIterator, class ConnectCondition> InputIterator connect(basic_socket<Protocol>& s, InputIterator first, ConnectCondition c); template<class Protocol, class InputIterator, class ConnectCondition> InputIterator connect(basic_socket<Protocol>& s, InputIterator first, ConnectCondition c, error_code& ec); template<class Protocol, class InputIterator, class ConnectCondition> InputIterator connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last, ConnectCondition c); template<class Protocol, class InputIterator, class ConnectCondition> InputIterator connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last, ConnectCondition c, error_code& ec); // asynchronous connect operations: template<class Protocol, class InputIterator, class CompletionToken> auto async_connect(basic_socket<Protocol>& s, InputIterator first, CompletionToken&& token); template<class Protocol, class InputIterator, class CompletionToken> auto async_connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last, CompletionToken&& token); template<class Protocol, class InputIterator, class ConnectCondition, class CompletionToken> auto async_connect(basic_socket<Protocol>& s, InputIterator first, ConnectCondition c, CompletionToken&& token); template<class Protocol, class InputIterator, class ConnectCondition, class CompletionToken> auto async_connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last, ConnectCondition c, CompletionToken&& token); } // inline namespace network_v1 } // namespace experimental template<> struct is_error_code_enum< experimental::network_v1::socket_errc> : public true_type {}; } // namespace std
The figure below illustrates relationships between various types described in this proposal. A solid line from A to B that is terminated by an open arrow indicates that A is derived from B. A solid line from A to B that starts with a diamond and is terminated by a solid arrow indicates that A contains an object of type B. A dotted line from A to B indicates that A is a typedef for the class template B with the specified template argument.
Several classes described in this Clause have a member type native_handle_type
, a member function
native_handle
, and member
functions that accept arguments of type native_handle_type
.
The presence of these members and their semantics is implementation-defined.
[Note: These members allow implementations to provide
access to their implementation details. Their names are specified to
facilitate portable compile-time detection. Actual use of these members
is inherently non-portable. For operating systems that are based on
POSIX, implementations are encouraged to define
the native_handle_type
for sockets as int
, representing
the native file descriptor associated with the socket. —end
note]
This clause defines an optional level of conformance, in the form of
additional member functions on types that satisfy Protocol
, Endpoint
, SettableSocketOption
, GettableSocketOption
or IoControlCommand
requirements.
[Note: When the additional member functions are available, C++ programs may extend the library to add support for other protocols and socket options. —end note]
An implementation's level of conformance shall be documented.
[Note: Implementations are encouraged to provide the additional member functions, where possible. It is intended that POSIX and Windows implementations will provide them. —end note]
For the purposes of this clause, implementations that provide the additional member functions are known as extensible implementations.
An endpoint must meet the requirements of CopyConstructible
types (C++ Std, 20.1.3), and the requirements of Assignable
types (C++ Std, 23.1).
In the table below, X
denotes an endpoint class, a
denotes a value of type X
,
and u
denotes an identifier.
Table 19. Endpoint requirements
expression |
type |
assertion/note |
---|---|---|
|
type meeting protocol requirements | |
| ||
| ||
|
|
In the table below, X
denotes an endpoint class, a
denotes a value of X
,
s
denotes a size in bytes,
and u
denotes an identifier.
Table 20. Endpoint requirements for extensible implementations
expression |
type |
assertion/note |
---|---|---|
|
a pointer |
Returns a pointer suitable for passing as the address
argument to POSIX functions such as |
|
a pointer |
Returns a pointer suitable for passing as the address
argument to POSIX functions such as |
|
|
Returns a value suitable for passing as the address_len
argument to POSIX functions such as |
|
post: | |
|
|
Returns a value suitable for passing as the address_len
argument to POSIX functions such as |
A protocol must meet the requirements of CopyConstructible
types (C++ Std, 20.1.3), and the requirements of Assignable
types (C++ Std, 23.1).
In the table below, X
denotes a protocol class, and a
denotes a value of X
.
Table 21. Protocol requirements
expression |
return type |
assertion/note |
---|---|---|
|
type meeting endpoint requirements |
In the table below, X
denotes a protocol class, and a
denotes a value of X
.
Table 22. Protocol requirements for extensible implementations
expression |
return type |
assertion/note |
---|---|---|
|
|
Returns a value suitable for passing as the domain
argument to POSIX |
|
|
Returns a value suitable for passing as the type
argument to POSIX |
|
|
Returns a value suitable for passing as the protocol
argument to POSIX |
In the table below, X
denotes a socket option class, a
denotes a value of X
,
p
denotes a value that
meets the protocol requirements,
and u
denotes an identifier.
Table 23. GettableSocketOption requirements for extensible implementations
expression |
type |
assertion/note |
---|---|---|
|
|
Returns a value suitable for passing as the level
argument to POSIX |
|
|
Returns a value suitable for passing as the option_name
argument to POSIX |
|
a pointer, convertible to |
Returns a pointer suitable for passing as the option_value
argument to POSIX |
|
|
Returns a value suitable for passing as the option_len
argument to POSIX |
|
post: |
In the table below, X
denotes a socket option class, a
denotes a value of X
,
p
denotes a value that
meets the protocol requirements,
and u
denotes an identifier.
Table 24. SettableSocketOption requirements for extensible implementations
expression |
type |
assertion/note |
---|---|---|
|
|
Returns a value suitable for passing as the level
argument to POSIX |
|
|
Returns a value suitable for passing as the option_name
argument to POSIX |
|
a pointer, convertible to |
Returns a pointer suitable for passing as the option_value
argument to POSIX |
|
|
Returns a value suitable for passing as the option_len
argument to POSIX |
In the table below, a
denotes a value of an I/O control command class.
Table 25. IoControlCommand requirements for extensible implementations
expression |
type |
assertion/note |
---|---|---|
|
|
Returns a value suitable for passing as the request
argument to POSIX |
|
a pointer, convertible to |
const error_category& socket_category() noexcept;
Returns: A reference to an object of a type derived from class error_category.
The object’s
default_error_condition
andequivalent
virtual functions shall behave as specified for the classerror_category
. The object’sname
virtual function shall return a pointer to the string"socket"
.
error_code make_error_code(socket_errc e) noexcept;
Returns:
error_code(static_cast<int>(e), socket_category())
.
error_condition make_error_condition(socket_errc e) noexcept;
Returns:
error_condition(static_cast<int>(e), socket_category())
.
namespace std { namespace experimental { inline namespace network_v1 { class socket_base { public: class broadcast; class debug; class do_not_route; class keep_alive; class linger; class out_of_band_inline; class receive_buffer_size; class receive_low_watermark; class reuse_address; class send_buffer_size; class send_low_watermark; typedef T1 shutdown_type; static const shutdown_type shutdown_receive; static const shutdown_type shutdown_send; static const shutdown_type shutdown_both; typedef T2 wait_type; static const wait_type wait_read; static const wait_type wait_write; static const wait_type wait_error; typedef T3 message_flags; static const message_flags message_peek; static const message_flags message_out_of_band; static const message_flags message_do_not_route; static const int max_connections; protected: socket_base(); ~socket_base(); }; } // inline namespace network_v1 } // namespace experimental } // namespace std
socket_base
defines several
member types:
— socket option classes broadcast
,
debug
, do_not_route
,
keep_alive
, linger
, out_of_band_inline
,
receive_buffer_size
, receive_low_watermark
, reuse_address
, send_buffer_size
,
and send_low_watermark
;
— an enumerated type, shutdown_type
;
— an enumerated type, wait_type
;
— a bitmask type, message_flags
.
The value max_connections
contains the implementation-defined limit on the length of the queue of
pending incoming connections.
The socket_base::broadcast
, socket_base::debug
,
socket_base::do_not_route
, socket_base::keep_alive
,
socket_base::out_of_band_inline
and socket_base::reuse_address
classes are boolean socket
options.
Boolean socket option classes satisfy the requirements for CopyConstructible
, Assignable
,
GettableSocketOption
,
and SettableSocketOption
.
Boolean socket option classes shall be defined as follows:
class C { public: // constructors: C(); explicit C(bool v); // members: C& operator=(bool v); bool value() const; operator bool() const; bool operator!() const; };
Extensible implementations shall provide the following member functions:
class C { public: template<class Protocol> int level(const Protocol& p) const; template<class Protocol> int name(const Protocol& p) const; template<class Protocol> unspecified* data(const Protocol& p); template<class Protocol> const unspecified* data(const Protocol& p) const; template<class Protocol> size_t size(const Protocol& p) const; template<class Protocol> void resize(const Protocol& p, size_t s); // remainder unchanged private: //int value_; exposition only };
The names and values used in the definition of the boolean socket option classes are described in the table below.
Table 26. Boolean socket options
C |
L |
N |
description |
---|---|---|---|
|
|
|
Determines whether a socket permits sending of broadcast messages, if supported by the protocol. |
|
|
|
Determines whether debugging information is recorded by the underlying protocol. |
|
|
|
Determines whether outgoing messages bypass standard routing facilities. |
|
|
|
Determines whether a socket permits sending of keep_alive messages, if supported by the protocol. |
|
|
|
Determines whether out-of-band data (also known as urgent data) is received inline. |
|
|
|
Determines whether the validation of endpoints used for binding a socket should allow the reuse of local endpoints, if supported by the protocol. |
[Note: The constants SOL_SOCKET
,
SO_BROADCAST
, SO_DEBUG
, SO_DONTROUTE
,
SO_KEEPALIVE
, SO_OOBINLINE
and SO_REUSEADDR
are defined in the POSIX header file sys/socket.h
. —end note]
C();
Postconditions:
!value()
.
explicit C(bool v);
Postconditions:
value() == v
.
C& operator=(bool v);
Returns:
*this
.
Postconditions:
value() == v
.
bool value() const;
Returns: The stored socket option value. For extensible implementations, returns
value_ != 0
.
operator bool() const;
Returns:
value()
.
bool operator!() const;
Returns:
!value()
.
template<class Protocol> int level(const Protocol& p) const;
Returns:
L
.
template<class Protocol> int name(const Protocol& p) const;
Returns:
N
.
template<class Protocol> unspecified* data(const Protocol& p);
Returns:
&value_
.
template<class Protocol> const unspecified* data(const Protocol& p) const;
Returns:
&value_
.
template<class Protocol> size_t size(const Protocol& p) const;
Returns:
sizeof(value_)
.
template<class Protocol> void resize(const Protocol& p, size_t s);
Throws:
length_error
ifs
is not a valid data size for the protocol specified byp
.
The socket_base::receive_buffer_size
, socket_base::receive_low_watermark
,
socket_base::send_buffer_size
and socket_base::send_low_watermark
classes are integral socket options.
Integral socket option classes satisfy the requirements for CopyConstructible
, Assignable
,
GettableSocketOption
,
and SettableSocketOption
.
Integral socket option classes shall be defined as follows:
class C { public: // constructors: C(); explicit C(int v); // members: C& operator=(int v); int value() const; };
Extensible implementations shall provide the following member functions:
class C { public: template<class Protocol> int level(const Protocol& p) const; template<class Protocol> int name(const Protocol& p) const; template<class Protocol> unspecified* data(const Protocol& p); template<class Protocol> const unspecified* data(const Protocol& p) const; template<class Protocol> size_t size(const Protocol& p) const; template<class Protocol> void resize(const Protocol& p, size_t s); // remainder unchanged private: //int value_; exposition only };
The names and values used in the definition of the integral socket option classes are described in the table below.
Table 27. Integral socket options
C |
L |
N |
description |
---|---|---|---|
|
|
|
Specifies the size of the receive buffer associated with a socket. |
|
|
|
Specifies the minimum number of bytes to process for socket input operations. |
|
|
|
Specifies the size of the send buffer associated with a socket. |
|
|
|
Specifies the minimum number of bytes to process for socket output operations. |
[Note: The constants SOL_SOCKET
,
SO_RCVBUF
, SO_RCVLOWAT
, SO_SNDBUF
and SO_SNDLOWAT
are defined
in the POSIX header file sys/socket.h
. —end note]
C();
Postconditions:
value() == 0
.
explicit C(int v);
Postconditions:
value() == v
.
C& operator=(int v);
Returns:
*this
.
Postconditions:
value() == v
.
int value() const;
Returns: The stored socket option value. For extensible implementations, returns
value_
.
template<class Protocol> int level(const Protocol& p) const;
Returns:
L
.
template<class Protocol> int name(const Protocol& p) const;
Returns:
N
.
template<class Protocol> unspecified* data(const Protocol& p);
Returns:
&value_
.
template<class Protocol> const unspecified* data(const Protocol& p) const;
Returns:
&value_
.
template<class Protocol> size_t size(const Protocol& p) const;
Returns:
sizeof(value_)
.
template<class Protocol> void resize(const Protocol& p, size_t s);
Throws:
length_error
ifs
is not a valid data size for the protocol specified byp
.
The linger
class represents
a socket option for controlling the behavior when a socket is closed and
unsent data is present.
linger
satisfies the requirements
for CopyConstructible
,
Assignable
, GettableSocketOption
, and SettableSocketOption
.
namespace std { namespace experimental { inline namespace network_v1 { class socket_base::linger { public: // constructors: linger(); linger(bool e, int t); // members: bool enabled() const; void enabled(bool e); int timeout() const; void timeout(int t); }; } // inline namespace network_v1 } // namespace experimental } // namespace std
Extensible implementations shall provide the following member functions:
namespace std { namespace experimental { inline namespace network_v1 { class socket_base::linger { public: template<class Protocol> int level(const Protocol& p) const; template<class Protocol> int name(const Protocol& p) const; template<class Protocol> unspecified* data(const Protocol& p); template<class Protocol> const unspecified* data(const Protocol& p) const; template<class Protocol> size_t size(const Protocol& p) const; template<class Protocol> void resize(const Protocol& p, size_t s); // remainder unchanged private: // ::linger value_; exposition only }; } // inline namespace network_v1 } // namespace experimental } // namespace std
linger();
Postconditions:
!enabled() && timeout() == 0
.
linger(bool e, int t);
Postconditions:
enabled() == e && timeout() == t
.
bool enabled() const;
Returns: The stored socket option value for whether linger on close is enabled. For extensible implementations, returns
value_.l_onoff != 0
.
void enabled(bool e);
Postconditions:
enabled() == e
.
int timeout() const;
Returns: The stored socket option value for the linger timeout, in seconds. For extensible implementations, returns
value_.l_linger
.
void timeout(int t);
Postconditions:
timeout() == t
.
template<class Protocol> int level(const Protocol& p) const;
Returns:
SOL_SOCKET
.
[Note: The constant
SOL_SOCKET
is defined in the POSIX header filesys/socket.h
. —end note]
template<class Protocol> int name(const Protocol& p) const;
Returns:
SO_LINGER
.
[Note: The constant
SO_LINGER
is defined in the POSIX header filesys/socket.h
. —end note]
template<class Protocol> unspecified* data(const Protocol& p) const;
Returns:
&value_
.
template<class Protocol> const unspecified* data(const Protocol& p) const;
Returns:
&value_
.
template<class Protocol> size_t size(const Protocol& p) const;
Returns:
sizeof(value_)
.
template<class Protocol> void resize(const Protocol& p, size_t s);
Throws:
length_error
ifs != sizeof(value_)
.
namespace std { namespace experimental { inline namespace network_v1 { template<class Protocol> class basic_socket : public socket_base { public: // types: typedef io_service::executor_type executor_type; typedef implementation defined native_handle_type; // See native handles typedef Protocol protocol_type; typedef typename Protocol::endpoint endpoint_type; // basic_socket operations: executor_type get_executor() noexcept; native_handle_type native_handle(); // See native handles void open(const protocol_type& protocol = protocol_type()); void open(const protocol_type& protocol, error_code& ec); void assign(const protocol_type& protocol, const native_handle_type& native_socket); // See native handles void assign(const protocol_type& protocol, const native_handle_type& native_socket, error_code& ec); // See native handles bool is_open() const; void close(); void close(error_code& ec); void cancel(); void cancel(error_code& ec); template<class SettableSocketOption> void set_option(const SettableSocketOption& option); template<class SettableSocketOption> void set_option(const SettableSocketOption& option, error_code& ec); template<class GettableSocketOption> void get_option(GettableSocketOption& option) const; template<class GettableSocketOption> void get_option(GettableSocketOption& option, error_code& ec) const; template<class IoControlCommand> void io_control(IoControlCommand& command); template<class IoControlCommand> void io_control(IoControlCommand& command, error_code& ec); void non_blocking(bool mode); void non_blocking(bool mode, error_code& ec); bool non_blocking() const; void native_non_blocking(bool mode); void native_non_blocking(bool mode, error_code& ec); bool native_non_blocking() const; bool at_mark() const; bool at_mark(error_code& ec) const; size_t available() const; size_t available(error_code& ec) const; void bind(const endpoint_type& endpoint); void bind(const endpoint_type& endpoint, error_code& ec); void shutdown(shutdown_type what); void shutdown(shutdown_type what, error_code& ec); endpoint_type local_endpoint() const; endpoint_type local_endpoint(error_code& ec) const; endpoint_type remote_endpoint() const; endpoint_type remote_endpoint(error_code& ec) const; void connect(const endpoint_type& endpoint); void connect(const endpoint_type& endpoint, error_code& ec); template<class CompletionToken> auto async_connect(const endpoint_type& endpoint, CompletionToken&& token); void wait(wait_type w); void wait(wait_type w, error_code& ec); template<class CompletionToken> auto async_wait(wait_type w, CompletionToken&& token); protected: // construct / copy / destroy: explicit basic_socket(io_service& ios); basic_socket(io_service& ios, const protocol_type& protocol); basic_socket(io_service& ios, const endpoint_type& endpoint); basic_socket(io_service& ios, const protocol_type& protocol, const native_handle_type& native_socket); // See native handles basic_socket(const basic_socket&) = delete; basic_socket(basic_socket&& rhs); template<class OtherProtocol> basic_socket(basic_socket<OtherProtocol>&& rhs); ~basic_socket(); basic_socket& operator=(const basic_socket&) = delete; basic_socket& operator=(basic_socket&& rhs); template<class OtherProtocol> basic_socket& operator=(basic_socket<OtherProtocol>&& rhs); }; } // inline namespace network_v1 } // namespace experimental } // namespace std
explicit basic_socket(io_service& ios);
Effects: Constructs an object of class
basic_socket<Protocol>
.
Postconditions:
—get_executor() == ios.get_executor()
.
—is_open() == false
.
basic_socket(io_service& ios, const protocol_type& protocol);
Effects: Constructs an object of class
basic_socket<Protocol>
, opening the socket as if by callingopen(protocol)
.
Postconditions:
—get_executor() == ios.get_executor()
.
—is_open() == true
.
—non_blocking() == false
.
basic_socket(io_service& ios, const endpoint_type& endpoint);
Effects: Constructs an object of class
basic_socket<Protocol>
, opening and binding the socket as if by calling:open(endpoint.protocol()); bind(endpoint);
Postconditions:
—get_executor() == ios.get_executor()
.
—is_open() == true
.
—non_blocking() == false
.
basic_socket(io_service& ios, const protocol_type& protocol, const native_handle_type& native_socket);
Effects: Constructs an object of class
basic_socket<Protocol>
, assigning the existing native socket into the object as if by callingassign(protocol, native_socket)
.
Postconditions:
—get_executor() == ios.get_executor()
.
—non_blocking() == false
.
[Note: Whether this function satisfies the postcondition
is_open() == true
is dependent on the implementation-defined semantics of thenative_handle
type. —end note]
basic_socket(basic_socket&& rhs);
Effects: Move constructs an object of class
basic_socket<Protocol>
that refers to the state originally represented byrhs
.
Postconditions:
—get_executor() == rhs.get_executor()
.
—is_open()
returns the same value asrhs.is_open()
prior to the constructor invocation.
—non_blocking()
returns the same value asrhs.non_blocking()
prior to the constructor invocation.
—rhs.is_open() == false
.
template<class OtherProtocol> basic_socket(basic_socket<OtherProtocol>&& rhs);
Requires:
OtherProtocol
is implicitly convertible toProtocol
.
Effects: Move constructs an object of class
basic_socket<Protocol>
that refers to the state originally represented byrhs
.
Postconditions:
—get_executor() == rhs.get_executor()
.
—is_open()
returns the same value asrhs.is_open()
prior to the constructor invocation.
—non_blocking()
returns the same value asrhs.non_blocking()
prior to the constructor invocation.
—rhs.is_open() == false
.
Remarks: This constructor shall not participate in overload resolution unless
OtherProtocol
is implicitly convertible toProtocol
.
~basic_socket();
Effects: If
is_open()
is true, cancels any asynchronous operations associated with the socket, disables the linger socket option to prevent the destructor from blocking, and releases socket resources as if by POSIXclose()
. Otherwise, no effect. Handlers for cancelled operations shall be passed an error codeec
such thatec == errc::operation_canceled
holds true.
basic_socket& operator=(basic_socket&& rhs);
Effects: If
is_open()
is true, cancels any asynchronous operations associated with the socket, disables the linger socket option to prevent the assignment from blocking, and releases socket resources as if by POSIXclose()
. Then moves into*this
the state originally represented byrhs
. Handlers for cancelled operations shall be passed an error codeec
such thatec == errc::operation_canceled
holds true.
Postconditions:
—get_executor() == rhs.get_executor()
.
—is_open()
returns the same value asrhs.is_open()
prior to the assignment.
—non_blocking()
returns the same value asrhs.non_blocking()
prior to the assignment.
—rhs.is_open() == false
.
Returns:
*this
.
template<class OtherProtocol> basic_socket& operator=(basic_socket<OtherProtocol>&& rhs);
Requires:
OtherProtocol
is implicitly convertible toProtocol
.
Effects: If
is_open()
is true, cancels any asynchronous operations associated with the socket, disables the linger socket option to prevent the assignment from blocking, and releases socket resources as if by POSIXclose()
. Then moves into*this
the state originally represented byrhs
. Handlers for cancelled operations shall be passed an error codeec
such thatec == errc::operation_canceled
holds true.
Postconditions:
—get_executor() == rhs.get_executor()
.
—is_open()
returns the same value asrhs.is_open()
prior to the assignment.
—non_blocking()
returns the same value asrhs.non_blocking()
prior to the assignment.
—rhs.is_open() == false
.
Returns:
*this
.
Remarks: This assignment operator shall not participate in overload resolution unless
OtherProtocol
is implicitly convertible toProtocol
.
executor_type get_executor() noexcept;
Returns: The associated executor.
native_handle_type native_handle();
Returns: The native representation of the socket implementation.
void open(const protocol_type& protocol); void open(const protocol_type& protocol, error_code& ec);
Requires:
!is_open()
.
Effects: Establishes the postcondition, as if by POSIX
socket()
.
Postconditions:
—is_open() == true
.
—non_blocking() == false
.
Error conditions:
—socket_errc::already_open
— if the requirement!is_open()
is unmet.
void assign(const protocol_type& protocol, const native_handle_type& native_socket); void assign(const protocol_type& protocol, const native_handle_type& native_socket, error_code& ec);
Requires:
!is_open()
.
Effects: Assigns the native socket handle to the socket object.
Postconditions:
non_blocking() == false
.
Error conditions:
—socket_errc::already_open
— if the requirement!is_open()
is unmet.
[Note: Whether this function satisfies the postcondition
is_open() == true
is dependent on the implementation-defined semantics of thenative_handle
type. —end note]
bool is_open() const;
Returns: A
bool
indicating whether the socket was opened by a previous call toopen
orassign
.
void close(); void close(error_code& ec);
Effects: If
is_open()
is true, cancels any asynchronous operations associated with the socket, and establishes the postcondition as if by POSIXclose()
. Otherwise, no effect. Handlers for cancelled asynchronous operations are passed an error codeec
such thatec == errc::operation_canceled
holds true.
Postconditions:
is_open() == false
.
void cancel(); void cancel(error_code& ec);
Effects: If
is_open()
is true, cancels any asynchronous operations associated with the socket. Handlers for cancelled asynchronous operations are passed an error codeec
such thatec == errc::operation_canceled
holds true.
Error conditions:
—errc::operation_not_supported
— Current conditions do not permit cancellation. The conditions under which cancellation of asynchronous operations is permitted are implementation-defined.
template<class SettableSocketOption> void set_option(const SettableSocketOption& option); template<class SettableSocketOption> void set_option(const SettableSocketOption& option, error_code& ec);
Effects: Sets an option on the socket, as if by POSIX
setsockopt()
.
template<class GettableSocketOption> void get_option(GettableSocketOption& option); template<class GettableSocketOption> void get_option(GettableSocketOption& option, error_code& ec);
Effects: Gets an option from the socket, as if by POSIX
getsockopt()
.
template<class IoControlCommand> void io_control(IoControlCommand& command); template<class IoControlCommand> void io_control(IoControlCommand& command, error_code& ec);
Effects: Executes an I/O control command on the socket, as if by POSIX
ioctl()
.
void non_blocking(bool mode); void non_blocking(bool mode, error_code& ec);
Requires:
is_open()
.
Effects: Sets the non-blocking mode of the socket. If
mode
is true, subsequent synchronous operations may fail with error conditionerrc::operation_would_block
if they are unable to perform the requested operation immediately. Ifmode
is false, subsequent synchronous operations shall block until complete.
Error conditions:
—errc::bad_file_descriptor
— ifis_open()
is false.
[Note: The non-blocking mode has no effect on the behavior of asynchronous operations. —end note]
bool non_blocking() const;
Returns: The non-blocking mode of the socket.
void native_non_blocking(bool mode); void native_non_blocking(bool mode, error_code& ec);
Effects: Sets the non-blocking mode of the underlying native socket, as if by POSIX
fcntl()
with commandF_SETFL
to add or clear the file status flagO_NONBLOCK
. This mode shall have no effect on the behavior of the synchronous or asynchronous operations specified in this clause.
Error conditions:
—errc::invalid_argument
— ifmode == false
andnon_blocking() == true
. [Note: As the combination does not make sense. —end note]
bool native_non_blocking() const;
Returns: The non-blocking mode of the underlying native socket.
Remarks: Implementations are permitted and encouraged to cache the native non-blocking mode that was applied through a prior call to
native_non_blocking
. Implementations may return an incorrect value if a program sets the non-blocking mode directly on the socket, by calling an operating system-specific function on the result ofnative_handle()
.
bool at_mark() const; bool at_mark(error_code& ec) const;
Effects: Determines if the socket is at the out-of-band data mark, as if by POSIX
sockatmark()
.
Returns: A
bool
indicating whether the socket is at the out-of-band data mark.
size_t available() const; size_t available(error_code& ec) const;
Requires:
is_open()
.
Returns: An indication of the number of bytes that may be read without blocking, or 0 if an error occurs.
Error conditions:
—errc::bad_file_descriptor
— ifis_open()
is false.
void bind(const endpoint_type& endpoint); void bind(const endpoint_type& endpoint, error_code& ec);
Effects: Binds the socket to the specified local endpoint, as if by POSIX
bind()
.
void shutdown(shutdown_type what); void shutdown(shutdown_type what, error_code& ec);
Effects: Shuts down all or part of a full-duplex connection for the socket, as if by POSIX
shutdown()
. Ifwhat
isshutdown_receive
, uses POSIXSHUT_RD
. Ifwhat
isshutdown_send
, uses POSIXSHUT_WR
. Ifwhat
isshutdown_both
, uses POSIXSHUT_RDWR
.
endpoint_type local_endpoint() const; endpoint_type local_endpoint(error_code& ec) const;
Effects: Determines the locally-bound endpoint associated with the socket, as if by POSIX
getsockname()
.
Returns: On success, the locally-bound endpoint. Otherwise
endpoint_type()
.
endpoint_type remote_endpoint() const; endpoint_type remote_endpoint(error_code& ec) const;
Effects: Determines the remote endpoint associated with the socket, as if by POSIX
getpeername()
.
Returns: On success, the remote endpoint. Otherwise
endpoint_type()
.
void connect(const endpoint_type& endpoint); void connect(const endpoint_type& endpoint, error_code& ec);
Effects: If
is_open()
is false, opens the socket by performingopen(endpoint.protocol(), ec)
; then, if no error has occurred, connects the socket to the specified remote endpoint, as if by POSIXconnect()
.
template<class CompletionToken> auto async_connect(const endpoint_type& endpoint, CompletionToken&& token);
Completion signature:
void(error_code ec)
.
Effects: If
is_open()
is false, opens the socket by performingopen(endpoint.protocol(), ec)
; then, if no error has occurred, initiates an asynchronous operation to connect the socket to the specified remote endpoint, as if by POSIXconnect()
.
When multiple asynchronous connect operations are initiated such that the operations may logically be performed in parallel, the behavior is unspecified. When an asynchronous connect operation and an asynchronous read or write operation are initiated such that they may logically be performed in parallel, the behavior is unspecified.
If a program performs a synchronous operation on the socket, other than
close
orcancel
, while there is an incomplete asynchronous connect operation, the behavior is unspecified.
void wait(wait_type w); void wait(wait_type w, error_code& ec);
Effects: Waits for the socket to be ready to read, ready to write, or to have error conditions pending, as if by POSIX
select()
.
template<class CompletionToken> auto async_wait(wait_type w, CompletionToken&& token);
Completion signature:
void(error_code ec)
.
Effects: Initiates an asynchronous operation to wait for the socket to be ready to read, ready to write, or to have error conditions pending, as if by POSIX
select()
.
When multiple asynchronous wait operations are initiated with the same
wait_type
value, all operations shall complete when the socket enters the corresponding ready state. The order of invocation of the handlers for these operations is unspecified.
namespace std { namespace experimental { inline namespace network_v1 { template<class Protocol> class basic_datagram_socket : public basic_socket<Protocol> { public: // types: typedef implementation defined native_handle_type; // See native handles typedef Protocol protocol_type; typedef typename Protocol::endpoint endpoint_type; // construct / copy / destroy: explicit basic_datagram_socket(io_service& ios); basic_datagram_socket(io_service& ios, const protocol_type& protocol); basic_datagram_socket(io_service& ios, const endpoint_type& endpoint); basic_datagram_socket(io_service& ios, const protocol_type& protocol, const native_handle_type& native_socket); basic_datagram_socket(const basic_datagram_socket&) = delete; basic_datagram_socket(basic_datagram_socket&& rhs); template<class OtherProtocol> basic_datagram_socket(basic_datagram_socket<OtherProtocol>&& rhs); ~basic_datagram_socket(); basic_datagram_socket& operator=(const basic_datagram_socket&) = delete; basic_datagram_socket& operator=(basic_datagram_socket&& rhs); template<class OtherProtocol> basic_datagram_socket& operator=(basic_datagram_socket<OtherProtocol>&& rhs); // basic_datagram_socket operations:: template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, error_code& ec); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, error_code& ec); template<class MutableBufferSequence, class CompletionToken> auto async_receive(const MutableBufferSequence& buffers, CompletionToken&& token); template<class MutableBufferSequence, class CompletionToken> auto async_receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, CompletionToken&& token); template<class MutableBufferSequence> size_t receive_from(const MutableBufferSequence& buffers, endpoint_type& sender); template<class MutableBufferSequence> size_t receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, error_code& ec); template<class MutableBufferSequence> size_t receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, socket_base::message_flags flags); template<class MutableBufferSequence> size_t receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, socket_base::message_flags flags, error_code& ec); template<class MutableBufferSequence, class CompletionToken> auto async_receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, CompletionToken&& token); template<class MutableBufferSequence, class CompletionToken> auto async_receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, socket_base::message_flags flags, CompletionToken&& token); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, error_code& ec); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags, error_code& ec); template<class ConstBufferSequence, class CompletionToken> auto async_send(const ConstBufferSequence& buffers, CompletionToken&& token); template<class ConstBufferSequence, class CompletionToken> auto async_send(const ConstBufferSequence& buffers, socket_base::message_flags flags, CompletionToken&& token); template<class ConstBufferSequence> size_t send_to(const ConstBufferSequence& buffers, const endpoint_type& destination); template<class ConstBufferSequence> size_t send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, error_code& ec); template<class ConstBufferSequence> size_t send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, socket_base::message_flags flags); template<class ConstBufferSequence> size_t send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, socket_base::message_flags flags, error_code& ec); template<class ConstBufferSequence, class CompletionToken> auto async_send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, CompletionToken&& token); template<class ConstBufferSequence, class CompletionToken> auto async_send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, socket_base::message_flags flags, CompletionToken&& token); }; } // inline namespace network_v1 } // namespace experimental } // namespace std
explicit basic_datagram_socket(io_service& ios);
Effects: Constructs an object of class
basic_datagram_socket<Protocol>
, initializing the base class withbasic_socket<Protocol>(ios)
.
basic_datagram_socket(io_service& ios, const protocol_type& protocol);
Effects: Constructs an object of class
basic_datagram_socket<Protocol>
, initializing the base class withbasic_socket<Protocol>(ios, protocol)
.
basic_datagram_socket(io_service& ios, const endpoint_type& endpoint);
Effects: Constructs an object of class
basic_datagram_socket<Protocol>
, initializing the base class withbasic_socket<Protocol>(ios, endpoint)
.
basic_datagram_socket(io_service& ios, const protocol_type& protocol, const native_handle_type& native_socket);
Effects: Constructs an object of class
basic_datagram_socket<Protocol>
, initializing the base class withbasic_socket<Protocol>(ios, protocol, native_socket)
.
basic_datagram_socket(basic_datagram_socket&& rhs);
Effects: Move constructs an object of class
basic_datagram_socket<Protocol>
, initializing the base class withbasic_socket<Protocol>(static_cast<basic_socket<Protocol>&&>(rhs))
.
template<class OtherProtocol> basic_datagram_socket(basic_datagram_socket<OtherProtocol>&& rhs);
Requires:
OtherProtocol
is implicitly convertible toProtocol
.
Effects: Move constructs an object of class
basic_datagram_socket<Protocol>
, initializing the base class withbasic_socket<Protocol>(static_cast<basic_socket<OtherProtocol>&&>(rhs))
.
Remarks: This constructor shall not participate in overload resolution unless
OtherProtocol
is implicitly convertible toProtocol
.
basic_datagram_socket& operator=(basic_datagram_socket&& rhs);
Effects: Calls
basic_socket<Protocol>::operator=(static_cast<basic_socket<Protocol>&&>(rhs))
.
Returns:
*this
.
template<class OtherProtocol> basic_datagram_socket& operator=(basic_datagram_socket<OtherProtocol>&& rhs);
Requires:
OtherProtocol
is implicitly convertible toProtocol
.
Effects: Calls
basic_socket<Protocol>::operator=(static_cast<basic_socket<OtherProtocol>&&>(rhs))
.
Returns:
*this
.
Remarks: This assignment operator shall not participate in overload resolution unless
OtherProtocol
is implicitly convertible toProtocol
.
template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, error_code& ec);
Returns:
receive(buffers, 0, ec)
.
template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, error_code& ec);
Effects: Reads data from a connection-mode or connectionless-mode socket, as if by POSIX
recvmsg()
, whereflags
specifies the type of message reception. [Note: It is normally used with connection-mode sockets because it does not permit the application to retrieve the source endpoint of received data. —end note]
Returns: On success, the number of bytes received. Otherwise
0
.
template<class MutableBufferSequence, class CompletionToken> auto async_receive(const MutableBufferSequence& buffers, CompletionToken&& token);
Returns:
async_receive(buffers, 0, forward<CompletionToken>(token))
.
template<class MutableBufferSequence, class CompletionToken> auto async_receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, CompletionToken&& token);
Completion signature:
void(error_code ec, size_t n)
.
Requires:
(flags & socket_base::message_peek) == 0
.
Effects: Initiates an asynchronous operation to read data from a connection-mode or connectionless-mode socket, as if by POSIX
recvmsg()
, whereflags
specifies the type of message reception. [Note: It is normally used with connection-mode sockets because it does not permit the application to retrieve the source endpoint of received data. —end note]
When multiple asynchronous receive operations with zero
flags
are initiated such that the operations may logically be performed in parallel, the implementation shall fill thebuffers
in the order in which the operations were issued. The order of invocation of the handlers for these operations is unspecified. When multiple asynchronous receive operations with non-zeroflags
are initiated such that operations may logically be performed in parallel, the behavior is unspecified.
If a program performs a synchronous operation on the socket, other than
close
,cancel
,send
orsend_to
, while there is a pending asynchronous receive operation, the behavior is unspecified.
If the operation completes successfully,
n
is the number of bytes received. Otherwisen
is0
.
Error conditions:
—errc::invalid_argument
— if(flags & socket_base::message_peek) != 0
.
template<class MutableBufferSequence> size_t receive_from(const MutableBufferSequence& buffers, endpoint_type& sender); template<class MutableBufferSequence> size_t receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, error_code& ec);
Returns:
receive_from(buffers, endpoint, 0, ec)
.
template<class MutableBufferSequence> size_t receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, socket_base::message_flags flags); template<class MutableBufferSequence> size_t receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, socket_base::message_flags flags, error_code& ec);
Effects: Reads data from a connection-mode or connectionless-mode socket, as if by POSIX
recvmsg()
, wheresender
is updated to reflect the origin of the data, andflags
specifies the type of message reception. [Note: It is normally used with connectionless-mode sockets because it permits the application to retrieve the source endpoint of received data. — end note]
Returns: On success, the number of bytes received. Otherwise
0
.
template<class MutableBufferSequence, class CompletionToken> auto async_receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, CompletionToken&& token);
Effects: Returns
async_receive_from(buffers, sender, 0, forward<CompletionToken>(token))
.
template<class MutableBufferSequence, class CompletionToken> auto async_receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, socket_base::message_flags flags, CompletionToken&& token);
Completion signature:
void(error_code ec, size_t n)
.
Requires:
(flags & socket_base::message_peek) == 0
.
Effects: Initiates an asynchronous operation to read data from a connection-mode or connectionless-mode socket, as if by POSIX
recvmsg()
, wheresender
is updated to reflect the source of the data, andflags
specifies the type of message reception. [Note: It is normally used with connectionless-mode sockets because it permits the application to retrieve the source endpoint of received data. — end note]
When multiple asynchronous receive operations with zero
flags
are initiated such that the operations may logically be performed in parallel, the implementation shall fill thebuffers
in the order in which the operations were issued. The order of invocation of the handlers for these operations is unspecified. When multiple asynchronous receive operations with non-zeroflags
are initiated such that operations may logically be performed in parallel, the behavior is unspecified.
If a program performs a synchronous operation on the socket, other than
close
,cancel
,send
orsend_to
, while there is a pending asynchronous receive operation, the behavior is unspecified.
If the operation completes successfully,
n
is the number of bytes received. Otherwisen
is0
.
Error conditions:
—errc::invalid_argument
— if(flags & socket_base::message_peek) != 0
.
template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, error_code& ec);
Returns:
send(buffers, 0, ec)
.
template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags, error_code& ec);
Effects: Writes data to a connected socket, as if by POSIX
sendmsg()
, whereflags
specifies the type of message transmission.
Returns: On success, the number of bytes sent. Otherwise
0
.
template<class ConstBufferSequence, class CompletionToken> auto async_send(const ConstBufferSequence& buffers, CompletionToken&& token);
Returns:
async_send(buffers, 0, forward<CompletionToken>(token))
.
template<class ConstBufferSequence, class CompletionToken> auto async_send(const ConstBufferSequence& buffers, socket_base::message_flags flags, CompletionToken&& token);
Completion signature:
void(error_code ec, size_t n)
.
Effects: Initiates an asynchronous operation to write data to a connected socket, as if by POSIX
sendmsg()
, whereflags
specifies the type of message transmission.
When multiple asynchronous send operations with zero
flags
are initiated such that the operations may logically be performed in parallel, the implementation shall transmit thebuffers
in the order in which the operations were issued. The order of invocation of the handlers for these operations is unspecified. When multiple asynchronous send operations with non-zeroflags
are initiated such that operations may logically be performed in parallel, the behavior is unspecified.
If a program performs a synchronous operation on the socket, other than
close
,cancel
,receive
orreceive_from
, while there is a pending asynchronous send operation, the behavior is unspecified.
If the operation completes successfully,
n
is the number of bytes sent. Otherwisen
is0
.
template<class ConstBufferSequence> size_t send_to(const ConstBufferSequence& buffers, const endpoint_type& destination); template<class ConstBufferSequence> size_t send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, error_code& ec);
Returns:
send_to(buffers, destination, 0, ec)
.
template<class ConstBufferSequence> size_t send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, socket_base::message_flags flags); template<class ConstBufferSequence> size_t send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, socket_base::message_flags flags, error_code& ec);
Effects: Writes data to a connection-mode or connectionless-mode socket, as if by POSIX
sendmsg()
, wheredestination
is the destination endpoint of the data, andflags
specifies the type of message transmission.
Returns: On success, the number of bytes sent. Otherwise
0
.
template<class ConstBufferSequence, class CompletionToken> auto async_send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, CompletionToken&& token);
Returns:
async_send_to(buffers, destination, 0, forward<CompletionToken>(token))
.
template<class ConstBufferSequence, class CompletionToken> auto async_send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, socket_base::message_flags flags, CompletionToken&& token);
Completion signature:
void(error_code ec, size_t n)
.
Effects: Initiates an asynchronous operation to write data to a connection-mode or connectionless-mode socket, as if by POSIX
sendmsg()
, wheredestination
is the destination endpoint of the data, andflags
specifies the type of message reception.
When multiple asynchronous send operations with zero
flags
are initiated such that the operations may logically be performed in parallel, the implementation shall transmit thebuffers
in the order in which the operations were issued. The order of invocation of the handlers for these operations is unspecified. When multiple asynchronous send operations with non-zeroflags
are initiated such that operations may logically be performed in parallel, the behavior is unspecified.
If a program performs a synchronous operation on the socket, other than
close
,cancel
,receive
orreceive_from
, while there is a pending asynchronous send operation, the behavior is unspecified.
If the operation completes successfully,
n
is the number of bytes sent. Otherwisen
is0
.
namespace std { namespace experimental { inline namespace network_v1 { template<class Protocol> class basic_stream_socket : public basic_socket<Protocol> { public: // types: typedef implementation defined native_handle_type; // See native handles typedef Protocol protocol_type; typedef typename Protocol::endpoint endpoint_type; // construct / copy / destroy: explicit basic_stream_socket(io_service& ios); basic_stream_socket(io_service& ios, const protocol_type& protocol); basic_stream_socket(io_service& ios, const endpoint_type& endpoint); basic_stream_socket(io_service& ios, const protocol_type& protocol, const native_handle_type& native_socket); basic_stream_socket(const basic_stream_socket&) = delete; basic_stream_socket(basic_stream_socket&& rhs); template<class OtherProtocol> basic_stream_socket(basic_stream_socket<OtherProtocol>&& rhs); ~basic_stream_socket(); basic_stream_socket& operator=(const basic_stream_socket&) = delete; basic_stream_socket& operator=(basic_stream_socket&& rhs); template<class OtherProtocol> basic_stream_socket& operator=(basic_stream_socket<OtherProtocol>&& rhs); // basic_stream_socket operations: template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, error_code& ec); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, error_code& ec); template<class MutableBufferSequence, class CompletionToken> auto async_receive(const MutableBufferSequence& buffers, CompletionToken&& token); template<class MutableBufferSequence, class CompletionToken> auto async_receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, CompletionToken&& token); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, error_code& ec); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags, error_code& ec); template<class ConstBufferSequence, class CompletionToken> auto async_send(const ConstBufferSequence& buffers, CompletionToken&& token); template<class ConstBufferSequence, class CompletionToken> auto async_send(const ConstBufferSequence& buffers, socket_base::message_flags flags, CompletionToken&& token); template<class MutableBufferSequence> size_t read_some(const MutableBufferSequence& buffers); template<class MutableBufferSequence> size_t read_some(const MutableBufferSequence& buffers, error_code& ec); template<class MutableBufferSequence, class CompletionToken> auto async_read_some(const MutableBufferSequence& buffers, CompletionToken&& token); template<class ConstBufferSequence> size_t write_some(const ConstBufferSequence& buffers); template<class ConstBufferSequence> size_t write_some(const ConstBufferSequence& buffers, error_code& ec); template<class ConstBufferSequence, class CompletionToken> auto async_write_some(const ConstBufferSequence& buffers, CompletionToken&& token); }; } // inline namespace network_v1 } // namespace experimental } // namespace std
Instances of the basic_stream_socket
class template meet the requirements for synchronous
read streams, synchronous
write streams, asynchronous
read streams, and asynchronous
write streams.
explicit basic_stream_socket(io_service& ios);
Effects: Constructs an object of class
basic_stream_socket<Protocol>
, initializing the base class withbasic_socket<Protocol>(ios)
.
basic_stream_socket(io_service& ios, const protocol_type& protocol);
Effects: Constructs an object of class
basic_stream_socket<Protocol>
, initializing the base class withbasic_socket<Protocol>(ios, protocol)
.
basic_stream_socket(io_service& ios, const endpoint_type& endpoint);
Effects: Constructs an object of class
basic_stream_socket<Protocol>
, initializing the base class withbasic_socket<Protocol>(ios, endpoint)
.
basic_stream_socket(io_service& ios, const protocol_type& protocol, const native_handle_type& native_socket);
Effects: Constructs an object of class
basic_stream_socket<Protocol>
, initializing the base class withbasic_socket<Protocol>(ios, protocol, native_socket)
.
basic_stream_socket(basic_stream_socket&& rhs);
Effects: Move constructs an object of class
basic_stream_socket<Protocol>
, initializing the base class withbasic_socket<Protocol>(static_cast<basic_socket<Protocol>&&>(rhs))
.
template<class OtherProtocol> basic_stream_socket(basic_stream_socket<OtherProtocol>&& rhs);
Requires:
OtherProtocol
is implicitly convertible toProtocol
.
Effects: Move constructs an object of class
basic_stream_socket<Protocol>
, initializing the base class withbasic_socket<Protocol>(static_cast<basic_socket<OtherProtocol>&&>(rhs))
.
Remarks: This constructor shall not participate in overload resolution unless
OtherProtocol
is implicitly convertible toProtocol
.
basic_stream_socket& operator=(basic_stream_socket&& rhs);
Effects: Calls
basic_socket<Protocol>::operator=(static_cast<basic_socket<Protocol>&&>(rhs))
.
Returns:
*this
.
template<class OtherProtocol> basic_stream_socket& operator=(basic_stream_socket<OtherProtocol>&& rhs);
Requires:
OtherProtocol
is implicitly convertible toProtocol
.
Effects: Calls
basic_socket<Protocol>::operator=(static_cast<basic_socket<OtherProtocol>&&>(rhs))
.
Returns:
*this
.
Remarks: This assignment operator shall not participate in overload resolution unless
OtherProtocol
is implicitly convertible toProtocol
.
template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, error_code& ec);
Returns:
receive(buffers, 0, ec)
.
template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, error_code& ec);
Effects: Reads data from the socket, as if by POSIX
recvmsg()
, whereflags
specifies the type of message reception. The operation shall not block ifbuffer_size(buffers) == 0
.
Returns: On success, the number of bytes received. Otherwise
0
.
Error conditions:
—stream_errc::eof
— if there is no data to be received and the peer performed an orderly shutdown.
template<class MutableBufferSequence, class CompletionToken> auto async_receive(const MutableBufferSequence& buffers, CompletionToken&& token);
Returns:
async_receive(buffers, 0, forward<CompletionToken>(token))
.
template<class MutableBufferSequence, class CompletionToken> auto async_receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, CompletionToken&& token);
Completion signature:
void(error_code ec, size_t n)
.
Requires:
(flags & socket_base::message_peek) == 0
.
Effects: Initiates an asynchronous operation to read data from the socket, as if by POSIX
recvmsg()
, whereflags
specifies the type of message reception. The operation shall complete immediately ifbuffer_size(buffers) == 0
.
When multiple asynchronous receive operations with zero
flags
are initiated such that the operations may logically be performed in parallel, the implementation shall fill thebuffers
in the order in which the operations were issued. The order of invocation of the handlers for these operations is unspecified. When multiple asynchronous receive operations with non-zeroflags
are initiated such that operations may logically be performed in parallel, the behavior is unspecified.
If a program performs a synchronous operation on the socket, other than
close
,cancel
, orsend
, while there is a pending asynchronous receive operation, the behavior is unspecified.
If the operation completes successfully,
n
is the number of bytes received. Otherwisen
is0
.
Error conditions:
—errc::invalid_argument
— if(flags & socket_base::message_peek) != 0
.
—stream_errc::eof
— if there is no data to be received and the peer performed an orderly shutdown.
template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, error_code& ec);
Returns:
send(buffers, 0, ec)
.
template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags, error_code& ec);
Effects: Writes data to the socket, as if by POSIX
sendmsg()
, whereflags
specifies the type of message transmission.
Returns: On success, the number of bytes sent. Otherwise
0
.
template<class ConstBufferSequence, class CompletionToken> auto async_send(const ConstBufferSequence& buffers, CompletionToken&& token);
Returns:
async_send(buffers, 0, forward<CompletionToken>(token))
.
template<class ConstBufferSequence, class CompletionToken> auto async_send(const ConstBufferSequence& buffers, socket_base::message_flags flags, CompletionToken&& token);
Completion signature:
void(error_code ec, size_t n)
.
Effects: Initiates an asynchronous operation to write data to the socket, as if by POSIX
sendmsg()
, whereflags
specifies the type of message transmission.
When multiple asynchronous send operations with zero
flags
are initiated such that the operations may logically be performed in parallel, the implementation shall transmit thebuffers
in the order in which the operations were issued. The order of invocation of the handlers for these operations is unspecified. When multiple asynchronous send operations with non-zeroflags
are initiated such that operations may logically be performed in parallel, the behavior is unspecified.
If a program performs a synchronous operation on the socket, other than
close
,cancel
, orreceive
, while there is a pending asynchronous send operation, the behavior is unspecified.
If the operation completes successfully,
n
is the number of bytes sent. Otherwisen
is0
.
template<class MutableBufferSequence> size_t read_some(const MutableBufferSequence& buffers); template<class MutableBufferSequence> size_t read_some(const MutableBufferSequence& buffers, error_code& ec);
Returns:
receive(buffers, 0, ec)
.
template<class MutableBufferSequence, class CompletionToken> auto async_read_some(const MutableBufferSequence& buffers, CompletionToken&& token);
Returns:
async_receive(buffers, 0, forward<CompletionToken>(token))
.
template<class ConstBufferSequence> size_t write_some(const ConstBufferSequence& buffers); template<class ConstBufferSequence> size_t write_some(const ConstBufferSequence& buffers, error_code& ec);
Returns:
send(buffers, 0, ec)
.
template<class ConstBufferSequence, class CompletionToken> auto async_write_some(const ConstBufferSequence& buffers, CompletionToken&& token);
Returns:
async_send(buffers, 0, forward<CompletionToken>(token))
.
namespace std { namespace experimental { inline namespace network_v1 { template<class Protocol> class basic_socket_acceptor : public socket_base { public: // types: typedef io_service::executor_type executor_type; typedef implementation defined native_handle_type; // See native handles typedef Protocol protocol_type; typedef typename Protocol::endpoint endpoint_type; // construct / copy / destroy: explicit basic_socket_acceptor(io_service& ios); basic_socket_acceptor(io_service& ios, const protocol_type& protocol); basic_socket_acceptor(io_service& ios, const endpoint_type& endpoint, bool reuse_addr = true); basic_socket_acceptor(io_service& ios, const protocol_type& protocol, const native_handle_type& native_acceptor); basic_socket_acceptor(const basic_socket_acceptor&) = delete; basic_socket_acceptor(basic_socket_acceptor&& rhs); template<class OtherProtocol> basic_socket_acceptor(basic_socket_acceptor<OtherProtocol>&& rhs); ~basic_socket_acceptor(); basic_socket_acceptor& operator=(const basic_socket_acceptor&) = delete; basic_socket_acceptor& operator=(basic_socket_acceptor&& rhs); template<class OtherProtocol> basic_socket_acceptor& operator=(basic_socket_acceptor<OtherProtocol>&& rhs); // basic_socket_acceptor operations: executor_type get_executor() noexcept; native_handle_type native_handle(); // See native handles void open(const protocol_type& protocol = protocol_type()); void open(const protocol_type& protocol, error_code& ec); void assign(const protocol_type& protocol, const native_handle_type& native_acceptor); // See native handles void assign(const protocol_type& protocol, const native_handle_type& native_acceptor, error_code& ec); // See native handles bool is_open() const; void close(); void close(error_code& ec); void cancel(); void cancel(error_code& ec); template<class SettableSocketOption> void set_option(const SettableSocketOption& option); template<class SettableSocketOption> void set_option(const SettableSocketOption& option, error_code& ec); template<class GettableSocketOption> void get_option(GettableSocketOption& option) const; template<class GettableSocketOption> void get_option(GettableSocketOption& option, error_code& ec) const; template<class IoControlCommand> void io_control(IoControlCommand& command); template<class IoControlCommand> void io_control(IoControlCommand& command, error_code& ec); void non_blocking(bool mode); void non_blocking(bool mode, error_code& ec); bool non_blocking() const; void native_non_blocking(bool mode); void native_non_blocking(bool mode, error_code& ec); bool native_non_blocking() const; void bind(const endpoint_type& endpoint); void bind(const endpoint_type& endpoint, error_code& ec); void listen(int backlog = max_connections); void listen(int backlog, error_code& ec); endpoint_type local_endpoint() const; endpoint_type local_endpoint(error_code& ec) const; void enable_connection_aborted(bool mode); bool enable_connection_aborted() const; template<class OtherProtocol> void accept(basic_socket<OtherProtocol>& socket); template<class OtherProtocol> void accept(basic_socket<OtherProtocol>& socket, error_code& ec); template<class OtherProtocol, class CompletionToken> auto async_accept(basic_socket<OtherProtocol>& socket, CompletionToken&& token); template<class OtherProtocol> void accept(basic_socket<OtherProtocol>& socket, endpoint_type& endpoint); template<class OtherProtocol> void accept(basic_socket<OtherProtocol>& socket, endpoint_type& endpoint, error_code& ec); template<class OtherProtocol, class CompletionToken> auto async_accept(basic_socket<OtherProtocol>& socket, endpoint_type& endpoint, CompletionToken&& token); void wait(wait_type w); void wait(wait_type w, error_code& ec); template<class CompletionToken> auto async_wait(wait_type w, CompletionToken&& token); }; } // inline namespace network_v1 } // namespace experimental } // namespace std
explicit basic_socket_acceptor(io_service& ios);
Effects: Constructs an object of class
basic_socket_acceptor<Protocol>
.
Postconditions:
—get_executor() == ios.get_executor()
.
—is_open() == false
.
basic_socket_acceptor(io_service& ios, const protocol_type& protocol);
Effects: Constructs an object of class
basic_socket_acceptor<Protocol>
, opening the acceptor as if by callingopen(protocol)
.
Postconditions:
—get_executor() == ios.get_executor()
.
—is_open() == true
.
—non_blocking() == false
.
—enable_connection_aborted() == false
.
basic_socket_acceptor(io_service& ios, const endpoint_type& endpoint, bool reuse_addr = true);
Effects: Constructs an object of class
basic_socket_acceptor<Protocol>
, opening and binding the acceptor as if by calling:open(endpoint.protocol()); if (reuse_addr) set_option(reuse_address(true)); bind(endpoint); listen();
Postconditions:
—get_executor() == ios.get_executor()
.
—is_open() == true
.
—non_blocking() == false
.
—enable_connection_aborted() == false
.
basic_socket_acceptor(io_service& ios, const protocol_type& protocol, const native_handle_type& native_acceptor);
Effects: Constructs an object of class
basic_socket_acceptor<Protocol>
, assigning the existing native acceptor into the object as if by callingassign(protocol, native_acceptor)
.
Postconditions:
—get_executor() == ios.get_executor()
.
—non_blocking() == false
.
—enable_connection_aborted() == false
.
[Note: Whether this function satisfies the postcondition
is_open() == true
is dependent on the implementation-defined semantics of thenative_handle
type. —end note]
basic_socket_acceptor(basic_socket_acceptor&& rhs);
Effects: Move constructs an object of class
basic_socket_acceptor<Protocol>
that refers to the state originally represented byrhs
.
Postconditions:
—get_executor() == rhs.get_executor()
.
—is_open()
returns the same value asrhs.is_open()
prior to the constructor invocation.
—non_blocking()
returns the same value asrhs.non_blocking()
prior to the constructor invocation.
—enable_connection_aborted()
returns the same value asrhs.enable_connection_aborted()
prior to the constructor invocation.
—rhs.is_open() == false
.
template<class OtherProtocol> basic_socket_acceptor(basic_socket_acceptor<OtherProtocol>&& rhs);
Requires:
OtherProtocol
is implicitly convertible toProtocol
.
Effects: Move constructs an object of class
basic_socket_acceptor<Protocol>
that refers to the state originally represented byrhs
.
Postconditions:
—get_executor() == rhs.get_executor()
.
—is_open()
returns the same value asrhs.is_open()
prior to the constructor invocation.
—non_blocking()
returns the same value asrhs.non_blocking()
prior to the constructor invocation.
—enable_connection_aborted()
returns the same value asrhs.enable_connection_aborted()
prior to the constructor invocation.
—rhs.is_open() == false
.
Remarks: This constructor shall not participate in overload resolution unless
OtherProtocol
is implicitly convertible toProtocol
.
~basic_socket_acceptor();
Effects: If
is_open()
is true, cancels any asynchronous operations associated with the acceptor, and releases acceptor resources as if by POSIXclose()
. Otherwise, no effect. Handlers for cancelled operations shall be passed an error codeec
such thatec == errc::operation_canceled
holds true.
basic_socket_acceptor& operator=(basic_socket_acceptor&& rhs);
Effects: If
is_open()
is true, cancels any asynchronous operations associated with the acceptor, and releases acceptor resources as if by POSIXclose()
. Then moves into*this
the state originally represented byrhs
. Handlers for cancelled operations shall be passed an error codeec
such thatec == errc::operation_canceled
holds true.
Postconditions:
—get_executor() == rhs.get_executor()
.
—is_open()
returns the same value asrhs.is_open()
prior to the assignment.
—non_blocking()
returns the same value asrhs.non_blocking()
prior to the assignment.
—enable_connection_aborted()
returns the same value asrhs.enable_connection_aborted()
prior to the assignment.
—rhs.is_open() == false
.
Returns:
*this
.
template<class OtherProtocol> basic_socket_acceptor& operator=(basic_socket_acceptor<OtherProtocol>&& rhs);
Requires:
OtherProtocol
is implicitly convertible toProtocol
.
Effects: If
is_open()
is true, cancels any asynchronous operations associated with the acceptor, and releases acceptor resources as if by POSIXclose()
. Then moves into*this
the state originally represented byrhs
. Handlers for cancelled operations shall be passed an error codeec
such thatec == errc::operation_canceled
holds true.
Postconditions:
—get_executor() == rhs.get_executor()
.
—is_open()
returns the same value asrhs.is_open()
prior to the assignment.
—non_blocking()
returns the same value asrhs.non_blocking()
prior to the assignment.
—enable_connection_aborted()
returns the same value asrhs.enable_connection_aborted()
prior to the assignment.
—rhs.is_open() == false
.
Returns:
*this
.
Remarks: This assignment operator shall not participate in overload resolution unless
OtherProtocol
is implicitly convertible toProtocol
.
executor_type get_executor() noexcept;
Returns: The associated executor.
native_handle_type native_handle();
Returns: The native representation of the acceptor implementation.
void open(const protocol_type& protocol); void open(const protocol_type& protocol, error_code& ec);
Requires:
!is_open()
.
Effects: Establishes the postcondition, as if by POSIX
socket()
.
Postconditions:
—is_open() == true
.
—non_blocking() == false
.
—enable_connection_aborted() == false
.
Error conditions:
—socket_errc::already_open
— if the requirement!is_open()
is unmet.
void assign(const protocol_type& protocol, const native_handle_type& native_acceptor); void assign(const protocol_type& protocol, const native_handle_type& native_acceptor, error_code& ec);
Requires:
!is_open()
.
Effects: Assigns the native acceptor handle to the acceptor object.
Postconditions:
—non_blocking() == false
.
—enable_connection_aborted() == false
.
Error conditions:
—socket_errc::already_open
— if the requirement!is_open()
is unmet.
[Note: Whether this function satisfies the postcondition
is_open() == true
is dependent on the implementation-defined semantics of thenative_handle
type. —end note]
bool is_open() const;
Returns: A
bool
indicating whether the acceptor was opened by a previous call toopen
orassign
.
void close(); void close(error_code& ec);
Effects: If
is_open()
is true, cancels any asynchronous operations associated with the acceptor, and establishes the postcondition as if by POSIXclose()
. Otherwise, no effect. Handlers for cancelled asynchronous operations are passed an error codeec
such thatec == errc::operation_canceled
holds true.
Postconditions:
is_open() == false
.
void cancel(); void cancel(error_code& ec);
Effects: If
is_open()
is true, cancels any asynchronous operations associated with the acceptor. Handlers for cancelled asynchronous operations are passed an error codeec
such thatec == errc::operation_canceled
holds true.
Error conditions:
—errc::operation_not_supported
— Current conditions do not permit cancellation. The conditions under which cancellation of asynchronous operations is permitted are implementation-defined.
template<class SettableSocketOption> void set_option(const SettableSocketOption& option); template<class SettableSocketOption> void set_option(const SettableSocketOption& option, error_code& ec);
Effects: Sets an option on the acceptor, as if by POSIX
setsockopt()
.
template<class GettableSocketOption> void get_option(GettableSocketOption& option); template<class GettableSocketOption> void get_option(GettableSocketOption& option, error_code& ec);
Effects: Gets an option from the acceptor, as if by POSIX
getsockopt()
.
template<class IoControlCommand> void io_control(IoControlCommand& command); template<class IoControlCommand> void io_control(IoControlCommand& command, error_code& ec);
Effects: Executes an I/O control command on the acceptor, as if by POSIX
ioctl()
.
void non_blocking(bool mode); void non_blocking(bool mode, error_code& ec);
Requires:
is_open()
.
Effects: Sets the non-blocking mode of the acceptor. If
mode
is true, subsequent synchronous operations may fail with error conditionerrc::operation_would_block
if they are unable to perform the requested operation immediately. Ifmode
is false, subsequent synchronous operations shall block until complete.
Error conditions:
—errc::bad_file_descriptor
— ifis_open()
is false.
[Note: The non-blocking mode has no effect on the behavior of asynchronous operations. —end note]
bool non_blocking() const;
Returns: The non-blocking mode of the acceptor.
void native_non_blocking(bool mode); void native_non_blocking(bool mode, error_code& ec);
Effects: Sets the non-blocking mode of the underlying native acceptor, as if by POSIX
fcntl()
with commandF_SETFL
to add or clear the file status flagO_NONBLOCK
. This mode shall have no effect on the behavior of the synchronous or asynchronous operations specified in this clause.
Error conditions:
—errc::invalid_argument
— ifmode == false
andnon_blocking() == true
. [Note: As the combination does not make sense. —end note]
bool native_non_blocking() const;
Returns: The non-blocking mode of the underlying native acceptor.
Remarks: Implementations are permitted and encouraged to cache the native non-blocking mode that was applied through a prior call to
native_non_blocking
. Implementations may return an incorrect value if a program sets the non-blocking mode directly on the acceptor, by calling an operating system-specific function on the result ofnative_handle()
.
void bind(const endpoint_type& endpoint); void bind(const endpoint_type& endpoint, error_code& ec);
Effects: Binds the acceptor to the specified local endpoint, as if by POSIX
bind()
.
void listen(int backlog = max_connections); void listen(int backlog, error_code& ec);
Effects: Marks the acceptor as ready to accept connections, as if by POSIX
listen()
. Ifbacklog == socket_base::max_connections
, the implementation shall set the acceptor's listen queue to the maximum allowable length.
endpoint_type local_endpoint() const; endpoint_type local_endpoint(error_code& ec) const;
Effects: Determines the locally-bound endpoint associated with the acceptor, as if by POSIX
getsockname()
.
Returns: On success, the locally-bound endpoint. Otherwise
endpoint_type()
.
void enable_connection_aborted(bool mode);
Requires:
is_open()
.
Effects: If
mode
is true, subsequent synchronous or asynchronous accept operations are permitted to fail with error conditionerrc::connection_aborted
. Ifmode
is false, subsequent accept operations shall not fail witherrc::connection_aborted
. [Note: Ifmode
is false, the implementation will restart the call to POSIXaccept()
if it fails withECONNABORTED
. —end note]
Error conditions:
—errc::bad_file_descriptor
— ifis_open()
is false.
bool enable_connection_aborted() const;
Returns: Whether accept operations are permitted to fail with
errc::connection_aborted
.
template<class OtherProtocol> void accept(basic_socket<OtherProtocol>& socket); template<class OtherProtocol> void accept(basic_socket<OtherProtocol>& socket, error_code& ec);
Requires:
—!socket.is_open()
.
—Protocol
andOtherProtocol
are the same type, orProtocol
is convertible toOtherProtocol
.
Effects: Associates
socket
with the first connection successfully extracted from the queue of pending connections of the acceptor, as if by POSIXaccept()
.
Error conditions:
—socket_errc::already_open
— if the requirement!socket.is_open()
is unmet.
template<class OtherProtocol, class CompletionToken> auto async_accept(basic_socket<OtherProtocol>& socket, CompletionToken&& token);
Completion signature:
void(error_code ec)
.
Requires:
—!socket.is_open()
.
—Protocol
andOtherProtocol
are the same type, orProtocol
is convertible toOtherProtocol
.
Effects: Initiates an asynchronous operation to associate
socket
with the first connection successfully extracted from the queue of pending connections of the acceptor, as if by POSIXaccept()
.
When multiple asynchronous accept operations are initiated such that the operations may logically be performed in parallel, the behavior is unspecified.
Error conditions:
—socket_errc::already_open
— if the requirement!socket.is_open()
is unmet.
template<class OtherProtocol> void accept(basic_socket<OtherProtocol>& socket, endpoint_type& endpoint); template<class OtherProtocol> void accept(basic_socket<OtherProtocol>& socket, endpoint_type& endpoint, error_code& ec);
Requires:
—!socket.is_open()
.
—Protocol
andOtherProtocol
are the same type, orProtocol
is convertible toOtherProtocol
.
Effects: Associates
socket
with the first connection successfully extracted from the queue of pending connections of the acceptor, as if by POSIXaccept()
. On success, setsendpoint
to the remote endpoint of the accepted connection.
Error conditions:
—socket_errc::already_open
— if the requirement!socket.is_open()
is unmet.
template<class OtherProtocol, class CompletionToken> auto async_accept(basic_socket<OtherProtocol>& socket, endpoint_type& endpoint, CompletionToken&& token);
Completion signature:
void(error_code ec)
.
Requires:
—!socket.is_open()
.
—Protocol
andOtherProtocol
are the same type, orProtocol
is convertible toOtherProtocol
.
Effects: Initiates an asynchronous operation to associate
socket
with the first connection successfully extracted from the queue of pending connections of the acceptor, as if by POSIXaccept()
. On success, setsendpoint
to the remote endpoint of the accepted connection.
When multiple asynchronous accept operations are initiated such that the operations may logically be performed in parallel, the behavior is unspecified.
Error conditions:
—socket_errc::already_open
— if the requirement!socket.is_open()
is unmet.
void wait(wait_type w); void wait(wait_type w, error_code& ec);
Effects: Waits for the acceptor to be ready to read, ready to write, or to have error conditions pending, as if by POSIX
select()
.
template<class CompletionToken> auto async_wait(wait_type w, CompletionToken&& token);
Completion signature:
void(error_code ec)
.
Effects: Initiates an asynchronous operation to wait for the acceptor to be ready to read, ready to write, or to have error conditions pending, as if by POSIX
select()
.
When multiple asynchronous wait operations are initiated with the same
wait_type
value, all operations shall complete when the acceptor enters the corresponding ready state. The order of invocation of the handlers for these operations is unspecified.
namespace std { namespace experimental { inline namespace network_v1 { template<class Protocol, class Clock, class WaitTraits> class basic_socket_streambuf : public basic_streambuf<char>, public basic_socket<Protocol> { public: // types: typedef typename Protocol::endpoint endpoint_type; typedef typename Clock::time_point time_point; typedef typename Clock::duration duration; // construct / destroy: basic_socket_streambuf(); virtual ~basic_socket_streambuf(); // members: basic_socket_streambuf<Protocol>* connect(const endpoint_type& e); template<class... Args> basic_socket_streambuf<Protocol>* connect(Args&&... ); basic_socket_streambuf<Protocol>* close(); error_code puberror() const; time_point expiry() const; void expires_at(const time_point& t); void expires_after(const duration& d); protected: // overridden virtual functions: virtual int_type underflow(); virtual int_type pbackfail(int_type c = traits_type::eof()); virtual int_type overflow(int_type c = traits_type::eof()); virtual int sync(); virtual streambuf* setbuf(char_type* s, streamsize n); virtual error_code error() const; private: error_code ec_; // exposition only time_point expiry_; // exposition only }; } // inline namespace network_v1 } // namespace experimental } // namespace std
The class basic_socket_streambuf<Protocol>
associates both the input sequence
and the output sequence with a socket. The input and output sequences are
independent and do not support seeking. Multibyte/wide character conversion
is not supported.
basic_socket_streambuf();
Effects: Constructs an object of class
basic_socket_streambuf<Protocol>
, initializing the base classes withbasic_streambuf<char>()
andbasic_socket<Protocol>(ios)
, whereios
is an unspecified object of classio_service
that has a longer lifetime than thebasic_socket<Protocol>
base.
Postconditions:
expiry() == Clock::max()
.
virtual ~basic_socket_streambuf();
Effects: Destroys an object of class
basic_socket_streambuf<Protocol>
. If a put area exists, callsoverflow(traits_type::eof())
to flush characters. [Note: The socket is closed by thebasic_socket<Protocol>
destructor. —end note]
basic_socket_streambuf<Protocol>* connect(const endpoint_type& e);
Effects: Resets the
streambuf
get and put areas, closes the socket as if by callingbasic_socket<Protocol>::close(ec_)
, then establishes a connection as if by performing:basic_socket<Protocol>::async_connect(e, unspecified);
ec_
is set to reflect the error code produced by the operation. If the operation does not complete before the absolute timeout specified byexpiry_
, the socket is closed andec_
is set toerrc::operation_canceled
.
Returns: if
!ec_
,this
; otherwise, a null pointer.
template<class... Args> basic_socket_streambuf<Protocol>* connect(Args&&... args);
Requires: The
Protocol
type must meet the requirements for an internet protocol.
Effects: Resets the
streambuf
get and put areas. Constructs an objectq
of typeProtocol::resolver::query
by initializing the object withq(forward<Args>(args)...)
, then establishes a connection as if by performing:typename Protocol::resolver resolver(ios); typename Protocol::resolver::iterator i = resolver.resolve(q, ec_); if (!ec_) std::experimental::network_v1::async_connect(*this, i, unspecified);where
ios
is an unspecified object of classio_service
.ec_
is set to reflect the error code produced by the asynchronous operation. If the operation does not complete before the absolute timeout specified byexpiry_
, the socket is closed andec_
is set toerrc::operation_canceled
.
Returns: if
!ec_
,this
; otherwise, a null pointer.
basic_socket_streambuf<Protocol>* close();
Effects: If a put area exists, calls
overflow(traits_type::eof())
to flush characters. Calls:this->basic_socket<Protocol>::close(ec_);then resets the get and put areas. If the call to
overflow
fails, or if!ec_
, thenclose
fails.
Returns:
this
on success, a null pointer otherwise.
error_code puberror() const;
Returns:
error()
.
time_point expiry() const;
Returns:
expiry_
.
void expires_at(const time_point& t);
Postconditions:
expiry_ == t
.
void expires_after(const duration& d);
Effects: Calls
expires_at(Clock::now() + d)
.
virtual int_type underflow();
Effects: Behaves according to the description of
basic_streambuf<char>::underflow()
, with the specialization that a sequence of characters is read from the input sequence as if by POSIXrecvmsg()
, andec_
is set to reflect the error code produced by the operation. If the operation does not complete before the absolute timeout specified byexpiry_
, the socket is closed andec_
is set toerrc::operation_canceled
.
Effects: Returns
traits_type::eof()
to indicate failure. Otherwise returnstraits_type::to_int_type(*gptr())
.
virtual int_type pbackfail(int_type c = traits_type::eof());
Effects: Puts back the character designated by
c
to the input sequence, if possible, in one of three ways:
— Iftraits_type::eq_int_type(c,traits_type::eof())
returnsfalse
, and if the function makes a putback position available, and iftraits_type::eq(traits_type::to_char_type(c),gptr()[-1])
returnstrue
, decrements the next pointer for the input sequence,gptr()
.
Returns:c
.
— Iftraits_type::eq_int_type(c,traits_type::eof())
returnsfalse
, and if the function makes a putback position available, and if the function is permitted to assign to the putback position, decrements the next pointer for the input sequence, and storesc
there.
Returns:c
.
— Iftraits_type::eq_int_type(c,traits_type::eof())
returnstrue
, and if either the input sequence has a putback position available or the function makes a putback position available, decrements the next pointer for the input sequence,gptr()
.
Returns:traits_type::not_eof(c)
.
Returns:
traits_type::eof()
to indicate failure.
Notes: The function does not put back a character directly to the input sequence. If the function can succeed in more than one of these ways, it is unspecified which way is chosen. The function can alter the number of putback positions available as a result of any call.
virtual int_type overflow(int_type c = traits_type::eof());
Effects: Behaves according to the description of
basic_streambuf<char>::overflow(c)
, except that the behavior of "consuming characters" is performed by output of the characters to the socket as if by one or more calls to POSIXsendmsg()
, andec_
is set to reflect the error code produced by the operation. If the operation does not complete before the absolute timeout specified byexpiry_
, the socket is closed andec_
is set toerrc::operation_canceled
.
Returns:
traits_type::not_eof(c)
to indicate success, andtraits_type::eof()
to indicate failure.
virtual int sync();
Effects: If a put area exists, calls
overflow(traits_type::eof())
to flush characters.
virtual streambuf* setbuf(char_type* s, streamsize n);
Effects: If
setbuf(0,0)
is called on a stream before any I/O has occurred on that stream, the stream becomes unbuffered. Otherwise the results are unspecified. "Unbuffered" means thatpbase()
andpptr()
always return null and output to the socket should appear as soon as possible.
virtual error_code error() const;
Returns:
ec_
.
namespace std { namespace experimental { inline namespace network_v1 { template<class Protocol, class Clock, class WaitTraits> class basic_socket_iostream : public basic_iostream<char> { public: // types: typedef typename Protocol::endpoint endpoint_type; typedef typename Clock::time_point time_point; typedef typename Clock::duration duration; // constructors: basic_socket_iostream(); template<class... Args> explicit basic_socket_iostream(Args&&... args); // members: template<class... Args> void connect(Args&&... args); void close(); basic_socket_streambuf<Protocol, StreamSocketService>* rdbuf() const; error_code error() const; time_point expiry() const; void expires_at(const time_point& t); void expires_after(const duration& d); private: basic_socket_streambuf<Protocol, Clock, WaitTraits> sb_; // exposition only }; } // inline namespace network_v1 } // namespace experimental } // namespace std
The class template basic_socket_iostream<Protocol, Clock, WaitTraits>
supports reading and writing from sockets.
It uses a basic_socket_streambuf<Protocol, Clock, WaitTraits>
object to control the associated sequences.
For the sake of exposition, the maintained data is presented here as:
— sb_
, the basic_socket_streambuf
object.
basic_socket_iostream();
Effects: Constructs an object of class
basic_socket_iostream<Protocol, Clock, WaitTraits>
, initializing the base class withbasic_iostream<char>(&sb_)
, initializingsb_
withbasic_socket_streambuf<Protocol, Clock, WaitTraits>()
, and performingthis->setf(std::ios_base::unitbuf)
.
template<class... Args> explicit basic_socket_iostream(Args&&... args);
Effects: Constructs an object of class
basic_socket_iostream<Protocol, Clock, WaitTraits>
, initializing the base class withbasic_iostream<char>(&sb_)
initializingsb_
withbasic_socket_streambuf<Protocol, Clock, WaitTraits>()
, and performingthis->setf(std::ios_base::unitbuf)
. Then callsrdbuf()->connect(forward<Args>(args)...)
. If that function returns a null pointer, callssetstate(failbit)
.
template<class... Args> void connect(Args&&... args);
Effects: Calls
rdbuf()->connect(forward<Args>(args)...)
. If that function returns a null pointer, callssetstate(failbit)
(which may throwios_base::failure
).
void close();
Effects: Calls
rdbuf()->close()
. If that function returns a null pointer, callssetstate(failbit)
(which may throwios_base::failure
).
basic_socket_streambuf<Protocol, StreamSocketService>* rdbuf() const;
Returns:
const_cast<basic_socket_streambuf<Protocol, Clock, WaitTraits>*>(&sb_)
.
error_code error() const;
Returns:
rdbuf()->puberror()
.
time_point expiry() const;
Returns:
rdbuf()->expiry()
.
void expires_at(const time_point& t);
Effects: Calls
rdbuf()->expires_at(t)
.
void expires_after(const duration& d);
Effects: Calls
rdbuf()->expires_after(d)
.
template<class Protocol, class InputIterator> InputIterator connect(basic_socket<Protocol>& s, InputIterator first); template<class Protocol, class InputIterator> InputIterator connect(basic_socket<Protocol>& s, InputIterator first, error_code& ec);
Requires: A default-constructed object of type
InputIterator
is an end-of-sequence iterator.
Returns:
connect(s, first, InputIterator(), ec)
.
template<class Protocol, class InputIterator> InputIterator connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last); template<class Protocol, class InputIterator> InputIterator connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last, error_code& ec);
Effects: If
s.is_open()
is true, performss.close(ec)
. Performsec.clear()
. Returns the first iteratori
in the range [first
,last
) for which the synchronous operations.connect(*i, ec)
succeeds. If no such iterator is found,ec
contains the error code produced by the last unsuccessful connect operation and the function returnslast
.
Error conditions:
—socket_errc::not_found
— iffirst == last
.
template<class Protocol, class InputIterator, class ConnectCondition> InputIterator connect(basic_socket<Protocol>& s, InputIterator first, ConnectCondition c); template<class Protocol, class InputIterator, class ConnectCondition> InputIterator connect(basic_socket<Protocol>& s, InputIterator first, ConnectCondition c, error_code& ec);
Requires: A default-constructed object of type
InputIterator
is an end-of-sequence iterator.
Returns:
connect(s, first, InputIterator(), c, ec)
.
template<class Protocol, class InputIterator, class ConnectCondition> InputIterator connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last, ConnectCondition c); template<class Protocol, class InputIterator, class ConnectCondition> InputIterator connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last, ConnectCondition c, error_code& ec);
Requires:
ConnectCondition
is a function object type meeting CopyConstructible requirements (C++ Std [copyconstructible]).
Effects: If
s.is_open()
is true, performss.close(ec)
. Performsec.clear()
. Returns the first iteratori
in the range [first
,last
) for whichc(ec, *i)
holds and, if so, for which the synchronous operations.connect(*i, ec)
succeeds. If no such iterator is found,ec
contains the error code produced by the last unsuccessful connect operation and the function returnslast
.
Error conditions:
—socket_errc::not_found
— iffirst == last
or if the function objectc
returned false for all iterators in the range.
template<class Protocol, class InputIterator, class CompletionToken> auto async_connect(basic_socket<Protocol>& s, InputIterator first, CompletionToken&& token);
Requires: A default-constructed object of type
InputIterator
is an end-of-sequence iterator.
Returns:
async_connect(s, first, InputIterator(), forward<CompletionToken>(token))
.
template<class Protocol, class InputIterator, class CompletionToken> auto async_connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last, CompletionToken&& token);
Completion signature:
void(error_code ec, InputIterator i)
.
Effects: If
s.is_open()
is true, performss.close(ec)
. Initiates an asynchronous operation to determine the first iteratori
in the range [first
,last
) for which the asynchronous operations.async_connect(*i, unspecified)
succeeds. If no such iterator is found,ec
contains the error code produced by the last unsuccessful connect operation andi
containslast
.
Error conditions:
—socket_errc::not_found
— iffirst == last
.
template<class Protocol, class InputIterator, class ConnectCondition, class CompletionToken> auto async_connect(basic_socket<Protocol>& s, InputIterator first, ConnectCondition c, CompletionToken&& token);
Requires: A default-constructed object of type
InputIterator
is an end-of-sequence iterator.
Returns:
async_connect(s, first, InputIterator(), c, forward<CompletionToken>(token))
.
template<class Protocol, class InputIterator, class ConnectCondition, class CompletionToken> auto async_connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last, ConnectCondition c, CompletionToken&& token);
Completion signature:
void(error_code ec, InputIterator i)
.
Requires:
ConnectCondition
is a function object type meeting CopyConstructible requirements (C++ Std [copyconstructible]).
Effects: If
s.is_open()
is true, performss.close(ec)
. Defineprevious_ec
as an object of typeerror_code
initialized such that!previous_ec
holds true. Initiates an asynchronous operation to determine the first iteratori
in the range [first
,last
) for whichc(previous_ec, *i)
holds and, if so, for which the asynchronous operations.async_connect(*i, unspecified)
succeeds. If an asynchronous operations.async_connect(*i, unspecified)
fails,previous_ec
is updated with the result of the operation. If no such iterator is found,ec
contains the error code produced by the last unsuccessful connect operation andi
containslast
.
Error conditions:
—socket_errc::not_found
— iffirst == last
or if the function objectc
returned false for all iterators in the range.
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { enum class resolver_errc { host_not_found = implementation defined, // EAI_NONAME host_not_found_try_again = implementation defined, // EAI_AGAIN service_not_found = implementation defined // EAI_SERVICE }; const error_category& resolver_category() noexcept; error_code make_error_code(resolver_errc e) noexcept; error_condition make_error_condition(resolver_errc e) noexcept; struct v4_mapped_t {}; constexpr v4_mapped_t v4_mapped; class address; class address_v4; class address_v6; class bad_address_cast; // address comparisons: bool operator==(const address&, const address&) noexcept; bool operator!=(const address&, const address&) noexcept; bool operator< (const address&, const address&) noexcept; bool operator> (const address&, const address&) noexcept; bool operator<=(const address&, const address&) noexcept; bool operator>=(const address&, const address&) noexcept; // address_v4 comparisons: bool operator==(const address_v4&, const address_v4&) noexcept; bool operator!=(const address_v4&, const address_v4&) noexcept; bool operator< (const address_v4&, const address_v4&) noexcept; bool operator> (const address_v4&, const address_v4&) noexcept; bool operator<=(const address_v4&, const address_v4&) noexcept; bool operator>=(const address_v4&, const address_v4&) noexcept; // address_v6 comparisons: bool operator==(const address_v6&, const address_v6&) noexcept; bool operator!=(const address_v6&, const address_v6&) noexcept; bool operator< (const address_v6&, const address_v6&) noexcept; bool operator> (const address_v6&, const address_v6&) noexcept; bool operator<=(const address_v6&, const address_v6&) noexcept; bool operator>=(const address_v6&, const address_v6&) noexcept; // address creation: address make_address(const char*); address make_address(const char*, error_code&) noexcept; address make_address(const string_view&); address make_address(const string_view&, error_code&) noexcept; // address_v4 creation: constexpr address_v4 make_address_v4(const address_v4::bytes_type&); constexpr address_v4 make_address_v4(unsigned long); constexpr address_v4 make_address_v4(v4_mapped_t, const address_v6&); address_v4 make_address_v4(const char*); address_v4 make_address_v4(const char*, error_code&) noexcept; address_v4 make_address_v4(const string_view&); address_v4 make_address_v4(const string_view&, error_code&) noexcept; // address_v6 creation: constexpr address_v6 make_address_v6(const address_v6::bytes_type&, unsigned long = 0); constexpr address_v6 make_address_v6(v4_mapped_t, const address_v4&) noexcept; address_v6 make_address_v6(const char*); address_v6 make_address_v6(const char*, error_code&) noexcept; address_v6 make_address_v6(const string_view&); address_v6 make_address_v6(const string_view&, error_code&) noexcept; // address I/O: template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>&, const address&); // address_v4 I/O: template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>&, const address_v4&); // address_v6 I/O: template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>&, const address_v6&); // address conversions: template<class T> constexpr T address_cast(const address&) noexcept(see below); template<class T> constexpr T address_cast(const address_v4&) noexcept(see below); template<class T> constexpr T address_cast(const address_v6&) noexcept(see below); class address_iterator_v4; class address_iterator_v6; class address_range_v4; class address_range_v6; class network_v4; class network_v6; // network_v4 comparisons: bool operator==(const network_v4&, const network_v4&) noexcept; bool operator!=(const network_v4&, const network_v4&) noexcept; // network_v6 comparisons: bool operator==(const network_v6&, const network_v6&) noexcept; bool operator!=(const network_v6&, const network_v6&) noexcept; // network_v4 creation: network_v4 make_network_v4(const address_v4&, unsigned short); network_v4 make_network_v4(const address_v4&, const address_v4&); network_v4 make_network_v4(const char*); network_v4 make_network_v4(const char*, error_code&) noexcept; network_v4 make_network_v4(const string_view&); network_v4 make_network_v4(const string_view&, error_code&) noexcept; // network_v6 creation: network_v6 make_network_v6(const address_v6&, unsigned short); network_v6 make_network_v6(const char*); network_v6 make_network_v6(const char*, error_code&) noexcept; network_v6 make_network_v6(const string_view&); network_v6 make_network_v6(const string_view&, error_code&) noexcept; // network_v4 I/O: template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>&, const network_v4&); // network_v6 I/O: template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>&, const network_v6&); template<class InternetProtocol> class basic_endpoint; // basic_endpoint comparisons: template<class InternetProtocol> bool operator==(const basic_endpoint<InternetProtocol>&, const basic_endpoint<InternetProtocol>&); template<class InternetProtocol> bool operator!=(const basic_endpoint<InternetProtocol>&, const basic_endpoint<InternetProtocol>&); template<class InternetProtocol> bool operator< (const basic_endpoint<InternetProtocol>&, const basic_endpoint<InternetProtocol>&); template<class InternetProtocol> bool operator> (const basic_endpoint<InternetProtocol>&, const basic_endpoint<InternetProtocol>&); template<class InternetProtocol> bool operator<=(const basic_endpoint<InternetProtocol>&, const basic_endpoint<InternetProtocol>&); template<class InternetProtocol> bool operator>=(const basic_endpoint<InternetProtocol>&, const basic_endpoint<InternetProtocol>&); // basic_endpoint I/O: template<class CharT, class Traits, class InternetProtocol> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>&, const basic_endpoint<InternetProtocol>&); class resolver_query_base; template<class InternetProtocol> basic_resolver_query; template<class InternetProtocol> basic_resolver_entry; template<class InternetProtocol> basic_resolver_iterator; template<class InternetProtocol> class basic_resolver; string host_name(); string host_name(error_code&); class tcp; // tcp comparisons: bool operator==(const tcp& a, const tcp& b); bool operator!=(const tcp& a, const tcp& b); class udp; // udp comparisons: bool operator==(const udp& a, const udp& b); bool operator!=(const udp& a, const udp& b); class v6_only; namespace unicast { class hops; } // namespace unicast namespace multicast { class join_group; class leave_group; class outbound_interface; class hops; class enable_loopback; } // namespace multicast } // namespace ip } // inline namespace network_v1 } // namespace experimental template<> struct is_error_condition_enum< experimental::network_v1::ip::resolver_errc> : public true_type {}; // hash support template<class T> struct hash; template<> struct hash<experimental::network_v1::ip::address>; template<> struct hash<experimental::network_v1::ip::address_v4>; template<> struct hash<experimental::network_v1::ip::address_v6>; } // namespace std
An internet protocol must meet the requirements for a protocol as well as the additional requirements listed below.
In the table below, X
denotes an internet protocol class, a
denotes a value of type X
,
and b
denotes a value
of type X
.
Table 28. InternetProtocol requirements
expression |
return type |
assertion/note |
---|---|---|
|
|
The type of a resolver for the protocol. |
|
|
Returns an object representing the IP version 4 protocol. |
|
|
Returns an object representing the IP version 6 protocol. |
|
convertible to |
Returns whether two protocol objects are equal. |
|
convertible to |
Returns |
const error_category& resolver_category() noexcept;
Returns: A reference to an object of a type derived from class error_category.
The object’s
default_error_condition
andequivalent
virtual functions shall behave as specified for the classerror_category
. The object’sname
virtual function shall return a pointer to the string"resolver"
.
error_code make_error_code(resolver_errc e) noexcept;
Returns:
error_code(static_cast<int>(e), resolver_category())
.
error_condition make_error_condition(resolver_errc e) noexcept;
Returns:
error_condition(static_cast<int>(e), resolver_category())
.
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { class address { public: // constructors: constexpr address() noexcept; constexpr address(const address& a) noexcept; template<class T> constexpr address(const T& t) noexcept(see below); // assignment: address& operator=(const address& a) noexcept; // members: constexpr bool is_unspecified() const noexcept; constexpr bool is_loopback() const noexcept; constexpr bool is_multicast() const noexcept; constexpr bool is_v4() const noexcept; constexpr bool is_v6() const noexcept; string to_string() const; }; // address comparisons: bool operator==(const address& a, const address& b) noexcept; bool operator!=(const address& a, const address& b) noexcept; bool operator< (const address& a, const address& b) noexcept; bool operator> (const address& a, const address& b) noexcept; bool operator<=(const address& a, const address& b) noexcept; bool operator>=(const address& a, const address& b) noexcept; // address creation: address make_address(const char* str); address make_address(const char* str, error_code& ec) noexcept; address make_address(const string_view& str); address make_address(const string_view& str, error_code& ec) noexcept; // address I/O: template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const address& addr); } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
constexpr address() noexcept;
Effects: Constructs an object of class
address
.
Postconditions: The postconditions of this function are indicated in the table below.
constexpr address(const address& a) noexcept;
Effects: Constructs an object of class
address
.
Postconditions:
*this == a
template<class T> constexpr address(const T& t) noexcept(see below);
Remarks: This constructor shall not participate in overload resolution unless
is_same<T, address>::value
isfalse
, and the expressionaddress_cast<address>(t)
is valid and yields an rvalue of typeaddress
. The expression insidenoexcept
shall be equivalent tonoexcept(address_cast<address>(t))
.
Effects: Constructs an object of type
address
with the result of the expressionaddress_cast<address>(t)
.
Throws: Nothing unless the expression
address_cast<address>(t)
throws an exception.
address& operator=(const address& a) noexcept;
Postconditions:
*this == a
Returns:
*this
constexpr bool is_unspecified() const noexcept;
Returns: If
is_v4() == true
, returnsaddress_cast<address_v4>(*this).is_unspecified()
. Ifis_v6() == true
, returnsaddress_cast<address_v6>(*this).is_unspecified()
. Otherwise returnsfalse
.
constexpr bool is_loopback() const noexcept;
Returns: If
is_v4() == true
, returnsaddress_cast<address_v4>(*this).is_loopback()
. Ifis_v6() == true
, returnsaddress_cast<address_v6>(*this).is_loopback()
. Otherwise returnsfalse
.
constexpr bool is_multicast() const noexcept;
Returns: If
is_v4() == true
, returnsaddress_cast<address_v4>(*this).is_multicast()
. Ifis_v6() == true
, returnsaddress_cast<address_v6>(*this).is_multicast()
. Otherwise returnsfalse
.
constexpr bool is_v4() const noexcept;
Returns:
true
if the object contains an IP version 4 address.
constexpr bool is_v6() const noexcept;
Returns:
true
if the object contains an IP version 6 address.
string to_string() const;
Returns: If
is_v4() == true
, returnsaddress_cast<address_v4>(*this).to_string()
. Ifis_v6() == true
, returnsaddress_cast<address_v6>(*this).to_string()
. Otherwise throwsbad_address_cast
.
bool operator==(const address& a, const address& b) noexcept;
Returns:
a_v4 == b_v4 && a_v6 == b_v6
, where:
—a_v4
is the value ofa.is_v4() ? address_cast<address_v4>(a) : address_v4()
;
—b_v4
isb.is_v4() ? address_cast<address_v4>(b) : address_v4()
;
—a_v6
isa.is_v6() ? address_cast<address_v6>(a) : address_v6()
; and
—b_v6
isb.is_v6() ? address_cast<address_v6>(b) : address_v6()
.
bool operator!=(const address& a, const address& b) noexcept;
Returns:
!(a == b)
.
bool operator< (const address& a, const address& b) noexcept;
Returns:
a_v6 < b_v6 || a_v6 == b_v6 && a_v4 < b_v4
, where:
—a_v4
is the value ofa.is_v4() ? address_cast<address_v4>(a) : address_v4()
;
—b_v4
isb.is_v4() ? address_cast<address_v4>(b) : address_v4()
;
—a_v6
isa.is_v6() ? address_cast<address_v6>(a) : address_v6()
; and
—b_v6
isb.is_v6() ? address_cast<address_v6>(b) : address_v6()
.
bool operator> (const address& a, const address& b) noexcept;
Returns:
b < a
.
bool operator<=(const address& a, const address& b) noexcept;
Returns:
!(b < a)
.
bool operator>=(const address& a, const address& b) noexcept;
Returns:
!(a < b)
.
address make_address(const char* str); address make_address(const char* str, error_code& ec) noexcept; address make_address(const string_view& str); address make_address(const string_view& str, error_code& ec) noexcept;
Effects: Converts a string representation of an address into an object of class
address
, as if by calling:address a; address_v6 v6a = make_address_v6(str, ec); if (!ec) a = v6a; else { address_v4 v4a = make_address_v4(str, ec); if (!ec) a = v4a; }
Returns:
a
.
template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const address& addr);
Effects: Outputs the string representation of the address to the stream, as if it were implemented as follows:
string s = addr.to_string(); for (string::iterator i = s.begin(); i != s.end(); ++i) os << os.widen(*i);
Returns:
os
.
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { class address_v4 { public: // types: struct bytes_type; // constructors: constexpr address_v4() noexcept; constexpr address_v4(const address_v4& a) noexcept; constexpr address_v4(const bytes_type& bytes); explicit constexpr address_v4(unsigned long val); // assignment: address_v4& operator=(const address_v4& a) noexcept; // members: constexpr bool is_unspecified() const noexcept; constexpr bool is_loopback() const noexcept; constexpr bool is_class_a() const noexcept; constexpr bool is_class_b() const noexcept; constexpr bool is_class_c() const noexcept; constexpr bool is_multicast() const noexcept; constexpr bytes_type to_bytes() const noexcept; constexpr unsigned long to_ulong() const noexcept; string to_string() const; // static members: static constexpr address_v4 any() noexcept; static constexpr address_v4 loopback() noexcept; static constexpr address_v4 broadcast() noexcept; static constexpr address_v4 broadcast(const address_v4& addr, const address_v4& mask) noexcept; }; // address_v4 comparisons: bool operator==(const address_v4& a, const address_v4& b) noexcept; bool operator!=(const address_v4& a, const address_v4& b) noexcept; bool operator< (const address_v4& a, const address_v4& b) noexcept; bool operator> (const address_v4& a, const address_v4& b) noexcept; bool operator<=(const address_v4& a, const address_v4& b) noexcept; bool operator>=(const address_v4& a, const address_v4& b) noexcept; // address_v4 creation: constexpr address_v4 make_address_v4(const address_v4::bytes_type& bytes); constexpr address_v4 make_address_v4(unsigned long val); constexpr address_v4 make_address_v4(v4_mapped_t, const address_v6& a); address_v4 make_address_v4(const char* str); address_v4 make_address_v4(const char* str, error_code& ec) noexcept; address_v4 make_address_v4(const string_view& str); address_v4 make_address_v4(const string_view& str, error_code& ec) noexcept; // address_v4 I/O: template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const address_v4& addr); } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { struct address_v4::bytes_type : array<unsigned char, 4> { template<class... T> explicit constexpr bytes_type(T... t) : array<unsigned char, 4>{{static_cast<unsigned char>(t)...}} {} }; } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
The ip::address_v4::bytes_type
type is a standard-layout
struct that provides a byte-level representation of an IPv4 address in
network byte order.
constexpr address_v4() noexcept;
Effects: Constructs an object of class
address_v4
.
Postconditions: The postconditions of this function are indicated in the table below.
constexpr address_v4(const address_v4& a) noexcept;
Effects: Constructs an object of class
address_v4
.
Postconditions:
*this == a
constexpr address_v4(const bytes_type& bytes);
Requires: Each element of
bytes
is in the range[0, 0xFF]
.
Throws:
out_of_range
if any element ofbytes
is not in the range[0, 0xFF]
. [Note: For implementations whereUCHAR_MAX == 0xFF
, no out-of-range detection is needed. —end note]
Postconditions:
to_bytes() == bytes
andto_ulong() == (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]
.
explicit constexpr address_v4(unsigned long val);
Requires:
val
is in the range[0, 0xFFFFFFFF]
.
Throws:
out_of_range
ifval
is not in the range[0, 0xFFFFFFFF]
. [Note: For implementations whereULONG_MAX == 0xFFFFFFFF
, no out-of-range detection is needed. —end note]
Postconditions:
to_ulong() == val
andto_bytes()
is{ (val >> 24) & 0xFF, (val >> 16) & 0xFF, (val >> 8) & 0xFF, val & 0xFF }
.
address_v4& operator=(const address_v4& a) noexcept;
Postconditions:
*this == a
Returns:
*this
constexpr bool is_unspecified() const noexcept;
Returns:
to_ulong() == 0
.
constexpr bool is_loopback() const noexcept;
Returns:
(to_ulong() & 0xFF000000) == 0x7F000000
.
constexpr bool is_class_a() const noexcept;
Returns:
(to_ulong() & 0x80000000) == 0
.
constexpr bool is_class_b() const noexcept;
Returns:
(to_ulong() & 0xC0000000) == 0x80000000
.
constexpr bool is_class_c() const noexcept;
Returns:
(to_ulong() & 0xE0000000) == 0xC0000000
.
constexpr bool is_multicast() const noexcept;
Returns:
(to_ulong() & 0xF0000000) == 0xE0000000
.
constexpr bytes_type to_bytes() const noexcept;
Returns: A representation of the address in network byte order.
constexpr unsigned long to_ulong() const noexcept;
Returns: A representation of the address in host byte order.
string to_string() const;
Effects: Converts an address into a string representation, as if by POSIX
inet_ntop()
when invoked with address familyAF_INET
.
Returns: If successful, the string representation of the address. Otherwise
string()
.
static constexpr address_v4 any() noexcept;
Returns:
address_v4()
.
static constexpr address_v4 loopback() noexcept;
Returns:
address_v4(0x7F000001)
.
static constexpr address_v4 broadcast() noexcept;
Returns:
address_v4(0xFFFFFFFF)
.
static constexpr address_v4 broadcast(const address_v4& addr, const address_v4& mask) noexcept;
Returns:
address_v4(addr.to_ulong() | ~mask.to_ulong())
.
bool operator==(const address_v4& a, const address_v4& b) noexcept;
Returns:
a.to_ulong() == b.to_ulong()
.
bool operator!=(const address_v4& a, const address_v4& b) noexcept;
Returns:
a.to_ulong() != b.to_ulong()
.
bool operator< (const address_v4& a, const address_v4& b) noexcept;
Returns:
a.to_ulong() < b.to_ulong()
.
bool operator> (const address_v4& a, const address_v4& b) noexcept;
Returns:
a.to_ulong() > b.to_ulong()
.
bool operator<=(const address_v4& a, const address_v4& b) noexcept;
Returns:
a.to_ulong() <= b.to_ulong()
.
bool operator>=(const address_v4& a, const address_v4& b) noexcept;
Returns:
a.to_ulong() >= b.to_ulong()
.
constexpr address_v4 make_address_v4(const address_v4::bytes_type& bytes);
Returns:
address_v4(bytes)
.
constexpr address_v4 make_address_v4(unsigned long val);
Returns:
address_v4(val)
.
constexpr address_v4 make_address_v4(v4_mapped_t, const address_v6& a);
Requires:
a.is_v4_mapped()
.
Returns: An
address_v4
object corresponding to the IPv4-mapped IPv6 address, as if computed by the following method:bytes_type v6b = a.to_bytes(); address_v4::bytes_type v4b(v6b[12], v6b[13], v6b[14], v6b[15]); return address_v4(v4b);
Throws:
bad_address_cast
ifa.is_v4_mapped()
is false.
address_v4 make_address_v4(const char* str); address_v4 make_address_v4(const char* str, error_code& ec) noexcept; address_v4 make_address_v4(const string_view& str); address_v4 make_address_v4(const string_view& str, error_code& ec) noexcept;
Effects: Converts a string representation of an address into a corresponding
address_v4
value, as if by POSIXinet_pton()
when invoked with address familyAF_INET
.
Returns: If successful, an
address_v4
value corresponding to the stringstr
. Otherwiseaddress_v4()
.
template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const address_v4& addr);
Effects: Outputs the string representation of the address to the stream, as if it were implemented as follows:
string s = addr.to_string(); for (string::iterator i = s.begin(); i != s.end(); ++i) os << os.widen(*i);
Returns:
os
.
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { class address_v6 { public: // types: struct bytes_type; // constructors: constexpr address_v6() noexcept; constexpr address_v6(const address_v6& a) noexcept; constexpr address_v6(const bytes_type& bytes, unsigned long scope = 0); // assignment: address_v4& operator=(const address_v4& a) noexcept; // members: void scope_id(unsigned long id) noexcept; constexpr unsigned long scope_id() const noexcept; constexpr bool is_unspecified() const noexcept; constexpr bool is_loopback() const noexcept; constexpr bool is_multicast() const noexcept; constexpr bool is_link_local() const noexcept; constexpr bool is_site_local() const noexcept; constexpr bool is_v4_mapped() const noexcept; constexpr bool is_multicast_node_local() const noexcept; constexpr bool is_multicast_link_local() const noexcept; constexpr bool is_multicast_site_local() const noexcept; constexpr bool is_multicast_org_local() const noexcept; constexpr bool is_multicast_global() const noexcept; constexpr bytes_type to_bytes() const noexcept; string to_string() const; // static members: static constexpr address_v6 any() noexcept; static constexpr address_v6 loopback() noexcept; }; // address_v6 comparisons: bool operator==(const address_v6& a, const address_v6& b) noexcept; bool operator!=(const address_v6& a, const address_v6& b) noexcept; bool operator< (const address_v6& a, const address_v6& b) noexcept; bool operator> (const address_v6& a, const address_v6& b) noexcept; bool operator<=(const address_v6& a, const address_v6& b) noexcept; bool operator>=(const address_v6& a, const address_v6& b) noexcept; // address_v6 creation: constexpr address_v6 make_address_v6(const address_v6::bytes_type& bytes, unsigned long scope_id = 0); constexpr address_v6 make_address_v6(v4_mapped_t, const address_v4& a) noexcept; address_v6 make_address_v6(const char* str); address_v6 make_address_v6(const char* str, error_code& ec) noexcept; address_v6 make_address_v6(const string_view& str); address_v6 make_address_v6(const string_vew& str, error_code& ec) noexcept; // address_v6 I/O: template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const address_v6& addr); } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
[Note: The implementations of the functions is_unspecified
, is_loopback
,
is_multicast
, is_link_local
, is_site_local
,
is_v4_mapped
, is_multicast_node_local
, is_multicast_link_local
, is_multicast_site_local
, is_multicast_org_local
and is_multicast_global
are determined by
[RFC4291]. —end note]
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { struct address_v6::bytes_type : array<unsigned char, 16> { template<class... T> explicit constexpr bytes_type(T... t) : array<unsigned char, 16>{{static_cast<unsigned char>(t)...}} {} }; } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
The ip::address_v6::bytes_type
type is a standard-layout
struct that provides a byte-level representation of an IPv6 address in
network byte order.
constexpr address_v6() noexcept;
Effects: Constructs an object of class
address_v6
.
Postconditions: The postconditions of this function are indicated in the table below.
constexpr address_v6(const address_v6& a) noexcept;
Effects: Constructs an object of class
address_v6
.
Postconditions:
*this == a
constexpr address_v6(const bytes_type& bytes, unsigned long scope = 0);
Requires: Each element of
bytes
is in the range[0, 0xFF]
.
Throws:
out_of_range
if any element ofbytes
is not in the range[0, 0xFF]
. [Note: For implementations whereUCHAR_MAX == 0xFF
, no out-of-range detection is needed. —end note]
Postconditions:
to_bytes() == bytes
andscope_id() == scope
.
address_v6& operator=(const address_v6& a) noexcept;
Postconditions:
*this == a
Returns:
*this
void scope_id(unsigned long id) noexcept;
Postconditions:
scope_id() == id
.
constexpr unsigned long scope_id() const noexcept;
Returns: The scope identifier associated with the address.
constexpr bool is_unspecified() const noexcept;
Returns: A boolean indicating whether the
address_v6
object represents an unspecified address, as if computed by the following method:bytes_type b = to_bytes(); return b[ 0] == 0 && b[ 1] == 0 && b[ 2] == 0 && b[ 3] == 0 && b[ 4] == 0 && b[ 5] == 0 && b[ 6] == 0 && b[ 7] == 0 && b[ 8] == 0 && b[ 9] == 0 && b[10] == 0 && b[11] == 0 && b[12] == 0 && b[13] == 0 && b[14] == 0 && b[15] == 0;
constexpr bool is_loopback() const noexcept;
Returns: A boolean indicating whether the
address_v6
object represents a loopback address, as if computed by the following method:bytes_type b = to_bytes(); return b[ 0] == 0 && b[ 1] == 0 && b[ 2] == 0 && b[ 3] == 0 && b[ 4] == 0 && b[ 5] == 0 && b[ 6] == 0 && b[ 7] == 0 && b[ 8] == 0 && b[ 9] == 0 && b[10] == 0 && b[11] == 0 && b[12] == 0 && b[13] == 0 && b[14] == 0 && b[15] == 1;
constexpr bool is_multicast() const noexcept;
Returns: A boolean indicating whether the
address_v6
object represents a multicast address, as if computed by the following method:bytes_type b = to_bytes(); return b[0] == 0xFF;
constexpr bool is_link_local() const noexcept;
Returns: A boolean indicating whether the
address_v6
object represents a unicast link-local address, as if computed by the following method:bytes_type b = to_bytes(); return b[0] == 0xFE && (b[1] & 0xC0) == 0x80;
constexpr bool is_site_local() const noexcept;
Returns: A boolean indicating whether the
address_v6
object represents a unicast site-local address, as if computed by the following method:bytes_type b = to_bytes(); return b[0] == 0xFE && (b[1] & 0xC0) == 0xC0;
constexpr bool is_v4_mapped() const noexcept;
Returns: A boolean indicating whether the
address_v6
object represents an IPv4-mapped IPv6 address, as if computed by the following method:bytes_type b = to_bytes(); return b[ 0] == 0 && b[ 1] == 0 && b[ 2] == 0 && b[ 3] == 0 && b[ 4] == 0 && b[ 5] == 0 && b[ 6] == 0 && b[ 7] == 0 && b[ 8] == 0 && b[ 9] == 0 && b[10] == 0xFF && b[11] == 0xFF;
constexpr bool is_multicast_node_local() const noexcept;
Returns: A boolean indicating whether the
address_v6
object represents a multicast node-local address, as if computed by the following method:bytes_type b = to_bytes(); return b[0] == 0xFF && (b[1] & 0x0F) == 0x01;
constexpr bool is_multicast_link_local() const noexcept;
Returns: A boolean indicating whether the
address_v6
object represents a multicast link-local address, as if computed by the following method:bytes_type b = to_bytes(); return b[0] == 0xFF && (b[1] & 0x0F) == 0x02;
constexpr bool is_multicast_site_local() const noexcept;
Returns: A boolean indicating whether the
address_v6
object represents a multicast site-local address, as if computed by the following method:bytes_type b = to_bytes(); return b[0] == 0xFF && (b[1] & 0x0F) == 0x05;
constexpr bool is_multicast_org_local() const noexcept;
Returns: A boolean indicating whether the
address_v6
object represents a multicast organization-local address, as if computed by the following method:bytes_type b = to_bytes(); return b[0] == 0xFF && (b[1] & 0x0F) == 0x08;
constexpr bool is_multicast_global() const noexcept;
Returns: A boolean indicating whether the
address_v6
object represents a multicast global address, as if computed by the following method:bytes_type b = to_bytes(); return b[0] == 0xFF && (b[1] & 0x0F) == 0x0E;
constexpr bytes_type to_bytes() const noexcept;
Returns: A representation of the address in network byte order.
string to_string() const;
Effects: Converts an address into a string representation. If
scope_id() == 0
, converts as if by POSIXinet_ntop()
when invoked with address familyAF_INET6
. Ifscope_id() != 0
, the format isaddress
%
scope-id
, whereaddress
is the string representation of the equivalent address havingscope_id() == 0
, andscope-id
is an implementation-defined string representation of the scope identifier.
Returns: If successful, the string representation of the address. Otherwise
string()
.
static constexpr address_v6 any() noexcept;
Returns:
address_v6()
.
static constexpr address_v6 loopback() noexcept;
Returns: An address
a
such that the conditiona.is_loopback()
holds.
bool operator==(const address_v6& a, const address_v6& b) noexcept;
Returns:
a.to_bytes() == b.to_bytes() && a.scope_id() == b.scope_id()
.
bool operator!=(const address_v6& a, const address_v6& b) noexcept;
Returns:
!(a == b)
.
bool operator< (const address_v6& a, const address_v6& b) noexcept;
Returns:
a.to_bytes() < b.to_bytes() || (!(b.to_bytes() < a.to_bytes()) && a.scope_id() < b.scope_id())
.
bool operator> (const address_v6& a, const address_v6& b) noexcept;
Returns:
b < a
.
bool operator<=(const address_v6& a, const address_v6& b) noexcept;
Returns:
!(b < a)
.
bool operator>=(const address_v6& a, const address_v6& b) noexcept;
Returns:
!(a < b)
.
constexpr address_v6 make_address_v6(const address_v6::bytes_type& bytes, unsigned long scope_id);
Returns:
address_v6(bytes, scope_id)
.
constexpr address_v6 make_address_v6(v4_mapped_t, const address_v4& a) noexcept;
Returns: An
address_v6
object containing the IPv4-mapped IPv6 address corresponding to the specified IPv4 address, as if computed by the following method:address_v4::bytes_type v4b = a.to_bytes(); bytes_type v6b(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, v4b[0], v4b[1], v4b[2], v4b[3]); return address_v6(v6b);
address_v6 make_address_v6(const char* str); address_v6 make_address_v6(const char* str, error_code& ec) noexcept; address_v6 make_address_v6(const string_view& str); address_v6 make_address_v6(const string_view& str, error_code& ec) noexcept;
Effects: Converts a string representation of an address into a corresponding
address_v6
value. The format is eitheraddress
oraddress
%
scope-id
, whereaddress
is in the format specified by POSIXinet_pton()
when invoked with address familyAF_INET6
, andscope-id
is an optional string specifying the scope identifier. All implementations shall accept asscope-id
a string representation of an unsigned decimal integer. It is implementation-defined whether alternative scope identifier representations are permitted. Ifscope-id
is not supplied, anaddress_v6
object shall be returned such thatscope_id() == 0
.
Returns: If successful, an
address_v6
value corresponding to the stringstr
. Otherwise returnsaddress_v6()
.
template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const address_v6& addr);
Effects: Outputs the string representation of the address to the stream, as if it were implemented as follows:
string s = addr.to_string(); for (string::iterator i = s.begin(); i != s.end(); ++i) os << os.widen(*i);
Returns:
os
.
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { class bad_address_cast : bad_cast { public: virtual const char* what() const noexcept; }; } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
Objects of type bad_address_cast
are thrown by a failed address_cast
.
template<class T> constexpr T address_cast(const address& a) noexcept(see below);
This function template shall participate in overload resolution only for the types
T
listed in the table below.
Table 32. template<class T> constexpr T address_cast(const address&) effects
T |
noexcept |
remarks |
---|---|---|
|
|
Returns |
|
|
If |
|
|
If |
template<class T> constexpr T address_cast(const address_v4& a) noexcept(see below);
This function template shall participate in overload resolution only for the types
T
listed in the table below.
Table 33. template<class T> constexpr T address_cast(const address_v4&) effects
T |
noexcept |
remarks |
---|---|---|
|
|
Returns a version-independent |
|
|
Returns |
|
Function overload is deleted. |
template<class T> constexpr T address_cast(const address_v6& a) noexcept(see below);
This function template shall participate in overload resolution only for the types
T
listed in the table below.
Table 34. template<class T> constexpr T address_cast(const address_v6&) effects
T |
noexcept |
remarks |
---|---|---|
|
|
Returns a version-independent |
|
Function overload is deleted. | |
|
|
Returns |
template<> struct hash<experimental::network_v1::ip::address>; template<> struct hash<experimental::network_v1::ip::address_v4>; template<> struct hash<experimental::network_v1::ip::address_v6>;
Requires: the template specializations shall meet the requirements of class template
hash
(C++ Std [unord.hash]).
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { class address_iterator_v4 { public: // types: typedef address_v4 value_type; typedef ptrdiff_t difference_type; typedef const address_v4* pointer; typedef const address_v4& reference; typedef input_iterator_tag iterator_category; // constructors: address_iterator_v4(const address_v4& a) noexcept; // members: const address_v4& operator*() const noexcept; const address_v4* operator->() const noexcept; address_iterator_v4& operator++() noexcept; address_iterator_v4& operator++(int) noexcept; address_iterator_v4& operator--() noexcept; address_iterator_v4& operator--(int) noexcept; // other members as required by C++ Std [input.iterators] private: address_v4 address_; // exposition only }; } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
address_iterator_v4(const address_v4& a) noexcept;
Effects: Constructs an object of type
address_iterator_v4
, initializingaddress_
witha
.
const address_v4& operator*() const noexcept;
Returns:
address_
.
const address_v4* operator->() const noexcept;
Returns:
&address_
.
address_iterator_v4& operator++() noexcept;
Effects: Sets
address_
to the next unique address in network byte order.
Returns:
*this
.
address_iterator_v4& operator++(int) noexcept;
Effects: Sets
address_
to the next unique address in network byte order.
Returns: The prior value of
*this
.
address_iterator_v4& operator--() noexcept;
Effects: Sets
address_
to the prior unique address in network byte order.
Returns:
*this
.
address_iterator_v4& operator--(int) noexcept;
Effects: Sets
address_
to the prior unique address in network byte order.
Returns: The prior value of
*this
.
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { class address_iterator_v6 { public: // types: typedef address_v6 value_type; typedef ptrdiff_t difference_type; typedef const address_v6* pointer; typedef const address_v6& reference; typedef input_iterator_tag iterator_category; // constructors: address_iterator_v6(const address_v6& a) noexcept; // members: const address_v6& operator*() const noexcept; const address_v6* operator->() const noexcept; address_iterator_v6& operator++() noexcept; address_iterator_v6& operator++(int) noexcept; address_iterator_v6& operator--() noexcept; address_iterator_v6& operator--(int) noexcept; // other members as required by C++ Std [input.iterators] private: address_v6 address_; // exposition only }; } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
address_iterator_v6(const address_v6& a) noexcept;
Effects: Constructs an object of type
address_iterator_v6
, initializingaddress_
witha
.
const address_v6& operator*() const noexcept;
Returns:
address_
.
const address_v6* operator->() const noexcept;
Returns:
&address_
.
address_iterator_v6& operator++() noexcept;
Effects: Sets
address_
to the next unique address in network byte order.
Returns:
*this
.
address_iterator_v6& operator++(int) noexcept;
Effects: Sets
address_
to the next unique address in network byte order.
Returns: The prior value of
*this
.
address_iterator_v6& operator--() noexcept;
Effects: Sets
address_
to the prior unique address in network byte order.
Returns:
*this
.
address_iterator_v6& operator--(int) noexcept;
Effects: Sets
address_
to the prior unique address in network byte order.
Returns: The prior value of
*this
.
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { class address_range_v4 { public: // types: typedef address_iterator_v4 iterator; // constructors: address_range_v4() noexcept; address_range_v4(const address_v4& first, const address_v4& last) noexcept; // members: iterator begin() const noexcept; iterator end() const noexcept; bool empty() const noexcept; size_t size() const noexcept; iterator find(const address_v4& addr) const noexcept; }; } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
address_range_v4() noexcept;
Effects: Constructs an object of type
address_range_v4
representing an empty range.
address_range_v4(const address_v4& first, const address_v4& last) noexcept;
Effects: Constructs an object of type
address_range_v4
representing the half open range [first
,last
).
iterator begin() const noexcept;
Returns: An iterator that points to the beginning of the range.
iterator end() const noexcept;
Returns: An iterator that points to the end of the range.
bool empty() const noexcept;
Returns:
true
if*this
represents an empty range, otherwisefalse
.
size_t size() const noexcept;
Returns: The number of unique addresses in the range.
iterator find(const address_v4& addr) const noexcept;
Returns: If
addr
is in the range, an iterator that points toaddr
; otherwise,end()
.
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { class address_range_v6 { public: // types: typedef address_iterator_v6 iterator; // constructors: address_range_v6() noexcept; address_range_v6(const address_v6& first, const address_v6& last) noexcept; // members: iterator begin() const noexcept; iterator end() const noexcept; bool empty() const noexcept; iterator find(const address_v6& addr) const noexcept; }; } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
address_range_v6() noexcept;
Effects: Constructs an object of type
address_range_v6
representing an empty range.
address_range_v6(const address_v6& first, const address_v6& last) noexcept;
Effects: Constructs an object of type
address_range_v6
representing the half open range [first
,last
).
iterator begin() const noexcept;
Returns: An iterator that points to the beginning of the range.
iterator end() const noexcept;
Returns: An iterator that points to the end of the range.
bool empty() const noexcept;
Returns:
true
if*this
represents an empty range, otherwisefalse
.
iterator find(const address_v6& addr) const noexcept;
Returns: If
addr
is in the range, an iterator that points toaddr
; otherwise,end()
.
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { class network_v4 { public: // constructors: network_v4() noexcept; network_v4(const address_v4& addr, unsigned short prefix_len); network_v4(const address_v4& addr, const address_v4& mask); // members: address_v4 address() const noexcept; unsigned short prefix_length() const noexcept; address_v4 netmask() const noexcept; address_v4 network() const noexcept; address_v4 broadcast() const noexcept; address_range_v4 hosts() const noexcept; network_v4 canonical() const noexcept; bool is_host() const noexcept; bool is_subnet_of(const network_v4& other) const noexcept; string to_string() const; }; // network_v4 comparisons: bool operator==(const network_v4& a, const network_v4& b) noexcept; bool operator!=(const network_v4& a, const network_v4& b) noexcept; // network_v4 creation: network_v4 make_network_v4(const address_v4& addr, unsigned short prefix_len); network_v4 make_network_v4(const address_v4& addr, const address_v4& mask); network_v4 make_network_v4(const char* str); network_v4 make_network_v4(const char* str, error_code& ec) noexcept; network_v4 make_network_v4(const string_view& str); network_v4 make_network_v4(const string_view& str, error_code& ec) noexcept; // network_v4 I/O: template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const network_v4& addr); } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
network_v4() noexcept;
Postconditions:
address().is_unspecified() == true
andprefix_length() == 0
.
network_v4(const address_v4& addr, unsigned short prefix_len);
Requires:
prefix_len <= 32
.
Postconditions:
address() == addr
andprefix_length() == prefix_len
.
Throws:
out_of_range
ifprefix_len > 32
.
network_v4(const address_v4& addr, const address_v4& mask);
Requires: Starting from the most significant bit in network byte order,
mask
contains zero or more contiguous non-zero bits. All other bits are zero.
Postconditions:
address() == addr
andprefix_length()
is equal to the number of contiguous non-zero bits.
Throws:
invalid_argument
ifmask
contains non-contiguous non-zero bits, or if the most significant bit is zero and any other bits are non-zero.
address_v4 address() const noexcept;
Returns: The address specified when the
network_v4
object was constructed.
unsigned short prefix_length() const noexcept;
Returns: The prefix length of the network.
address_v4 netmask() const noexcept;
Returns: An
address_v4
object withprefix_length()
contiguous non-zero bits set, starting from the most significant bit in network byte order. All other bits are zero.
address_v4 network() const noexcept;
Returns: An
address_v4
object with the firstprefix_length()
bits, starting from the most significant bit in network byte order, set to the corresponding bit value ofaddress()
. All other bits are zero.
address_v4 broadcast() const noexcept;
Returns: An
address_v4
object with the firstprefix_length()
bits, starting from the most significant bit in network byte order, set to the corresponding bit value ofaddress()
. All other bits are non-zero.
address_range_v4 hosts() const noexcept;
Returns: If
is_host() == true
, anaddress_range_v4
object representing the single addressaddress().
Otherwise, anaddress_range_v4
object representing the range of unique host IP addresses in the network.
network_v4 canonical() const noexcept;
Returns:
network_v4(network(), prefix_length())
.
bool is_host() const noexcept;
Returns:
true
ifprefix_length() == 32
, otherwisefalse
.
bool is_subnet_of(const network_v4& other) const noexcept;
Returns:
true
ifother.prefix_length() < prefix_length()
andnetwork_v4(address(), other.prefix_length()).canonical() == other.canonical()
.
string to_string() const;
Returns: A string
s
computed as if by:
std::string s = address().to_string(); s += '/'; s += to_string(prefix_length());
bool operator==(const network_v4& a, const network_v4& b) noexcept;
Returns:
true
ifa.address() == b.address()
anda.prefix_length() == b.prefix_length()
, otherwisefalse
.
bool operator!=(const network_v4& a, const network_v4& b) noexcept;
Returns:
!(a == b)
.
network_v4 make_network_v4(const address_v4& addr, unsigned short prefix_len);
Returns:
network_v4(addr, prefix_len)
.
network_v4 make_network_v4(const address_v4& addr, const address_v4& mask);
Returns:
network_v4(addr, mask)
.
network_v4 make_network_v4(const char* str); network_v4 make_network_v4(const char* str, error_code& ec) noexcept; network_v4 make_network_v4(const string_view& str); network_v4 make_network_v4(const string_view& str, error_code& ec) noexcept;
Returns: If
str
contains a value of the form address'/'
prefix-length, anetwork_v4
object constructed with the result of applyingmake_address_v4()
to the address portion of the string, and the result of converting prefix-length to an integer of typeunsigned short
. Otherwise returnsnetwork_v4()
and setsec
to reflect the error.
template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const network_v4& net);
Effects: Outputs the string representation of the network to the stream, as if it were implemented as follows:
string s = net.to_string(); for (string::iterator i = s.begin(); i != s.end(); ++i) os << os.widen(*i);
Returns:
os
.
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { class network_v6 { public: // constructors: network_v6() noexcept; network_v6(const address_v6& addr, unsigned short prefix_len); // members: address_v6 address() const noexcept; unsigned short prefix_length() const noexcept; address_v6 network() const noexcept; address_range_v6 hosts() const noexcept; network_v6 canonical() const noexcept; bool is_host() const noexcept; bool is_subnet_of(const network_v6& other) const noexcept; string to_string() const; }; // network_v6 comparisons: bool operator==(const network_v6& a, const network_v6& b) noexcept; bool operator!=(const network_v6& a, const network_v6& b) noexcept; // network_v6 creation: network_v6 make_network_v6(const address_v6& addr, unsigned short prefix_len); network_v6 make_network_v6(const char* str); network_v6 make_network_v6(const char* str, error_code& ec) noexcept; network_v6 make_network_v6(const string_v6& str); network_v6 make_network_v6(const string_v6& str, error_code& ec) noexcept; // network_v6 I/O: template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const network_v6& addr); } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
network_v6() noexcept;
Postconditions:
address().is_unspecified() == true
andprefix_length() == 0
.
network_v6(const address_v6& addr, unsigned short prefix_len);
Requires:
prefix_len <= 128
.
Postconditions:
address() == addr
andprefix_length() == prefix_len
.
Throws:
out_of_range
ifprefix_len > 128
.
address_v6 address() const noexcept;
Returns: The address specified when the
network_v6
object was constructed.
unsigned short prefix_length() const noexcept;
Returns: The prefix length of the network.
address_v6 network() const noexcept;
Returns: An
address_v6
object with the firstprefix_length()
bits, starting from the most significant bit in network byte order, set to the corresponding bit value ofaddress()
. All other bits are zero.
address_range_v6 hosts() const noexcept;
Returns: If
is_host() == true
, anaddress_range_v6
object representing the single addressaddress().
Otherwise, anaddress_range_v6
object representing the range of unique host IP addresses in the network.
network_v6 canonical() const noexcept;
Returns:
network_v6(network(), prefix_length())
.
bool is_host() const noexcept;
Returns:
true
ifprefix_length() == 128
, otherwisefalse
.
bool is_subnet_of(const network_v6& other) const noexcept;
Returns:
true
ifother.prefix_length() < prefix_length()
andnetwork_v6(address(), other.prefix_length()).canonical() == other.canonical()
.
string to_string() const;
Returns: A string
s
computed as if by:
std::string s = address().to_string(); s += '/'; s += to_string(prefix_length());
bool operator==(const network_v6& a, const network_v6& b) noexcept;
Returns:
true
ifa.address() == b.address()
anda.prefix_length() == b.prefix_length()
, otherwisefalse
.
bool operator!=(const network_v6& a, const network_v6& b) noexcept;
Returns:
!(a == b)
.
network_v6 make_network_v6(const address_v6& addr, unsigned short prefix_len);
Returns:
network_v6(addr, prefix_len)
.
network_v6 make_network_v6(const char* str); network_v6 make_network_v6(const char* str, error_code& ec) noexcept; network_v6 make_network_v6(const string_v6& str); network_v6 make_network_v6(const string_v6& str, error_code& ec) noexcept;
Returns: If
str
contains a value of the form address'/'
prefix-length, anetwork_v6
object constructed with the result of applyingmake_address_v6()
to the address portion of the string, and the result of converting prefix-length to an integer of typeunsigned short
. Otherwise returnsnetwork_v6()
and setsec
to reflect the error.
template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const network_v6& net);
Effects: Outputs the string representation of the network to the stream, as if it were implemented as follows:
string s = net.to_string(); for (string::iterator i = s.begin(); i != s.end(); ++i) os << os.widen(*i);
Returns:
os
.
Instances of the basic_endpoint
class template meet the requirements for an Endpoint
.
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { template<class InternetProtocol> class basic_endpoint { public: // types: typedef InternetProtocol protocol_type; // constructors: basic_endpoint(); basic_endpoint(const InternetProtocol& proto, unsigned short port_num); basic_endpoint(const ip::address& addr, unsigned short port_num); // members: InternetProtocol protocol() const; ip::address address() const; void address(const ip::address& addr); unsigned short port() const; void port(unsigned short port_num); }; // basic_endpoint comparisons: template<class InternetProtocol> bool operator==(const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b); template<class InternetProtocol> bool operator!=(const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b); template<class InternetProtocol> bool operator< (const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b); template<class InternetProtocol> bool operator> (const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b); template<class InternetProtocol> bool operator<=(const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b); template<class InternetProtocol> bool operator>=(const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b); // basic_endpoint I/O: template<class CharT, class Traits, class InternetProtocol> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const basic_endpoint<InternetProtocol>& ep); } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
Extensible implementations shall provide the following member functions:
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { template<class InternetProtocol> class basic_endpoint { public: unspecified* data(); const unspecified* data() const; size_t size() const; void resize(size_t s); size_t capacity() const; // remainder unchanged private: // sockaddr_storage data_; exposition only }; } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
basic_endpoint();
Effects: Constructs an object of class
basic_endpoint<InternetProtocol>
.
Postconditions: The postconditions of this function are indicated in the table below.
Table 35. basic_endpoint<InternetProtocol>::basic_endpoint() effects
expression |
value |
---|---|
|
|
|
|
basic_endpoint(const InternetProtocol& proto, unsigned short port_num);
Effects: Constructs an object of class
basic_endpoint<InternetProtocol>
with the specified protocol and port number.
Postconditions: The postconditions of this function are indicated in the table below.
Table 36. basic_endpoint<InternetProtocol>::basic_endpoint(const InternetProtocol&, unsigned short) effects
expression |
value |
---|---|
|
|
|
|
basic_endpoint(const ip::address& addr, unsigned short port_num);
Effects: Constructs an object of class
basic_endpoint<InternetProtocol>
with the specified address and port number.
Postconditions: The postconditions of this function are indicated in the table below.
Table 37. basic_endpoint<InternetProtocol>::basic_endpoint(const ip::address&, unsigned short) effects
expression |
value |
---|---|
|
|
|
|
InternetProtocol protocol() const;
Returns:
Protocol::v6()
if the expressionaddress().is_v6()
is true, otherwiseProtocol::v4()
.
ip::address address() const;
Returns: The address associated with the endpoint.
void address(const ip::address& addr);
Effects: Modifies the address associated with the endpoint.
Postconditions:
address() == addr
.
unsigned short port() const;
Returns: The port number associated with the endpoint.
void port(unsigned short port_num);
Effects: Modifies the port number associated with the endpoint.
Postconditions:
port() == port_num
.
template<class InternetProtocol> bool operator==(const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b);
Returns:
a.address() == b.address() && a.port() == b.port())
.
template<class InternetProtocol> bool operator!=(const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b);
Returns:
!(a == b)
.
template<class InternetProtocol> bool operator< (const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b);
Returns:
a.address() < b.address() || (!(b.address() < a.address()) && a.port() < b.port())
.
template<class InternetProtocol> bool operator> (const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b);
Returns:
b < a
.
template<class InternetProtocol> bool operator<=(const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b);
Returns:
!(b < a)
.
template<class InternetProtocol> bool operator>=(const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b);
Returns:
!(a < b)
.
template<class CharT, class Traits, class InternetProtocol> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const basic_endpoint<InternetProtocol>& ep);
Effects: Outputs a representation of the endpoint to the stream, as if it were implemented as follows:
basic_ostringstream<CharT, Traits> ss; if (ep.protocol() == Protocol::v6()) ss << ss.widen('[') << ss.address() << ss.widen(']'); else ss << ep.address(); ss << ss.widen(':') << ep.port(); os << ss.str();
Returns:
os
.
[Note: The representation of the endpoint when it contains an IP version 6 address is based on [RFC2732]. —end note]
unspecified* data();
Returns:
&data_
.
const unspecified* data() const;
Returns:
&data_
.
size_t size() const;
Returns:
sizeof(sockaddr_in6)
ifprotocol().family() == AF_INET
, otherwisesizeof(sockaddr_in)
.
void resize(size_t s);
Throws:
length_error
if the conditionprotocol().family() == AF_INET6 && s != sizeof(sockaddr_in6)
||
protocol().family() != AF_INET6 && s != sizeof(sockaddr_in)
is true.
size_t capacity() const;
Returns:
sizeof(data_)
.
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { class resolver_query_base { public: typedef T1 flags; static const flags passive; static const flags canonical_name; static const flags numeric_host; static const flags numeric_service; static const flags v4_mapped; static const flags all_matching; static const flags address_configured; protected: resolver_query_base(); ~resolver_query_base(); }; } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
resolver_query_base
defines
a bitmask type, flags
.
The flags constants have bitwise-distinct values. The meanings and POSIX
equivalents for each flag are defined in the table below.
Table 38. resolver flags
flag |
meaning |
POSIX equivalent |
---|---|---|
|
Returned endpoints are intended for use as locally bound socket endpoints. |
|
|
Determine the canonical name of the host specified in the query. |
|
|
Host name should be treated as a numeric string defining an IPv4 or IPv6 address and no host name resolution should be attempted. |
|
|
Service name should be treated as a numeric string defining a port number and no service name resolution should be attempted. |
|
|
If the query protocol is specified as an IPv6 protocol, return IPv4-mapped IPv6 addresses on finding no IPv6 addresses. |
|
|
If used with |
|
|
Only return IPv4 addresses if a non-loopback IPv4 address is configured for the system. Only return IPv6 addresses if a non-loopback IPv6 address is configured for the system. |
|
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { template<class InternetProtocol> class basic_resolver_entry { public: // types: typedef InternetProtocol protocol_type; typedef typename InternetProtocol::endpoint endpoint_type; // constructors: basic_resolver_entry(); basic_resolver_entry(const endpoint_type& ep, const string_view& h, const string_view& s); // members: endpoint_type endpoint() const; operator endpoint_type() const; string host_name() const; string service_name() const; }; } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
basic_resolver_entry();
Effects: Constructs an object of class
basic_resolver_entry<InternetProtocol>
.
Postconditions: The postconditions of this function are indicated in the table below.
Table 39. basic_resolver_entry<InternetProtocol>::basic_resolver_entry() effects
expression |
value |
---|---|
|
|
|
|
|
|
basic_resolver_entry(const endpoint_type& ep, const string_view& h, const string_view& s);
Effects: Constructs an object of class
basic_resolver_entry<InternetProtocol>
with the specified endpoint, host name and service name.
Postconditions: The postconditions of this function are indicated in the table below.
Table 40. basic_resolver_entry<InternetProtocol>::basic_resolver_entry() effects
expression |
value |
---|---|
|
|
|
|
|
|
endpoint_type endpoint() const;
Returns: The endpoint associated with the resolver entry.
operator endpoint_type() const;
Returns:
endpoint()
.
string host_name() const;
Returns: The host name associated with the resolver entry.
string service_name() const;
Returns: The service name associated with the resolver entry.
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { template<class InternetProtocol> class basic_resolver_iterator { public: // types: typedef basic_resolver_entry<InternetProtocol> value_type; typedef ptrdiff_t difference_type; typedef const basic_resolver_entry<InternetProtocol>* pointer; typedef const basic_resolver_entry<InternetProtocol>& reference; typedef forward_iterator_tag iterator_category; typedef InternetProtocol protocol_type; typedef typename InternetProtocol::endpoint endpoint_type; // constructors: basic_resolver_iterator(); // other members as required by C++ Std [forward.iterators] }; } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { template<class InternetProtocol> class basic_resolver_query : public resolver_query_base { public: // types: typedef InternetProtocol protocol_type; // constructors: basic_resolver_query(); basic_resolver_query(const string_view& service_name, flags f = passive | address_configured); basic_resolver_query(const InternetProtocol& proto, const string_view& service_name, flags f = passive | address_configured); basic_resolver_query(const string_view& host_name, const string_view& service_name, flags f = address_configured); basic_resolver_query(const InternetProtocol& proto, const string_view& host_name, const string_view& service_name, flags f = address_configured); }; } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
The basic_resolver_query
class encapsulates values used in name resolution. The meanings of the
constructor arguments are defined below as if the name resolution is performed
using POSIX getaddrinfo()
:
— proto is used to populate the ai_family
,
ai_socktype
and ai_protocol
fields of the addrinfo
structure passed as the hints
argument to POSIX getaddrinfo()
.
— host_name is passed as the nodename
argument to POSIX getaddrinfo()
.
— service_name is passed as the servname
argument to POSIX getaddrinfo()
.
— flags is used to populate the ai_flags
field of the addrinfo
structure
passed as the hints argument to POSIX
getaddrinfo()
.
If a default-constructed basic_resolver_query
object is used in a call to basic_resolver<>::resolve()
, the results are undefined.
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { template<class InternetProtocol> class basic_resolver { public: // types: typedef io_service::executor_type executor_type; typedef InternetProtocol protocol_type; typedef typename InternetProtocol::endpoint endpoint_type; typedef basic_resolver_query<InternetProtocol> query; typedef basic_resolver_iterator<InternetProtocol> iterator; // construct / copy / destroy: explicit basic_resolver(io_service& ios); basic_resolver(const basic_resolver&) = delete; basic_resolver(basic_resolver&& rhs); ~basic_resolver(); basic_resolver& operator=(const basic_resolver&) = delete; basic_resolver& operator=(basic_resolver&& rhs); // basic_resolver operations: executor_type get_executor() noexcept; void cancel(); iterator resolve(const query& q); iterator resolve(const query& q, error_code& ec); template<class CompletionToken> auto async_resolve(const query& q, CompletionToken&& token); iterator resolve(const endpoint_type& e); iterator resolve(const endpoint_type& e, error_code& ec); template<class CompletionToken> auto async_resolve(const endpoint_type& e, CompletionToken&& token); }; } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
explicit basic_resolver(io_service& ios);
Effects: Constructs an object of class
basic_resolver<InternetProtocol>
.
Postconditions:
get_executor() == ios.get_executor()
.
basic_resolver(basic_resolver&& rhs);
Effects: Move constructs an object of class
basic_resolver<InternetProtocol>
that refers to the state originally represented byrhs
.
Postconditions:
get_executor() == rhs.get_executor()
.
~basic_resolver();
Effects: Destroys the resolver, cancelling any asynchronous operations associated with the resolver as if by calling
cancel()
.
basic_resolver& operator=(basic_resolver&& rhs);
Effects: Cancels any outstanding asynchronous operations associated with
*this
as if by callingcancel()
, then moves into*this
the state originally represented byrhs
.
Postconditions:
get_executor() == ios.get_executor()
.
Returns:
*this
.
executor_type& get_executor() noexcept;
Returns: The associated executor.
void cancel();
Effects: Causes any outstanding asynchronous resolve operations to complete as soon as possible. Handlers for cancelled operations shall be passed an error code
ec
such thatec == errc::operation_canceled
holds true.
iterator resolve(const query& q); iterator resolve(const query& q, error_code& ec);
Effects: Translates a query into a sequence of
basic_resolver_entry<InternetProtocol>
objects, as if by POSIXgetaddrinfo()
.
Returns: On success, an iterator object
i
such that the conditioni != iterator()
holds. Otherwiseiterator()
.
template<class CompletionToken> auto async_resolve(const query& q, CompletionToken&& token);
Completion signature:
void(error_code ec, iterator i)
.
Effects: Initiates an asynchronous operation to translate a query into a sequence of
basic_resolver_entry<InternetProtocol>
objects, as if by POSIXgetaddrinfo()
. If the operation completes successfully, the handler is passed an iterator objecti
such that the conditioni != iterator()
holds. Otherwise,i
isiterator()
.
iterator resolve(const endpoint_type& e); iterator resolve(const endpoint_type& e, error_code& ec);
Effects: Translates an endpoint into a sequence of zero or one
basic_resolver_entry<InternetProtocol>
objects, as if by POSIXgetnameinfo()
.
Returns: On success, an iterator object
i
such that the conditioni != iterator()
holds. Otherwiseiterator()
.
template<class CompletionToken> auto async_resolve(const endpoint_type& e, CompletionToken&& token);
Completion signature:
void(error_code ec, iterator i)
.
Effects: Initiates an asynchronous operation to translate an endpoint into a sequence of zero or one
basic_resolver_entry<InternetProtocol>
objects, as if by POSIXgetnameinfo()
. If the operation completes successfully, the handler is passed an iterator objecti
such that the conditioni != iterator()
holds. Otherwise,i
isiterator()
.
string host_name(); string host_name(error_code&);
Returns: The standard host name for the current machine, determined as if by POSIX
gethostname()
.
The tcp
class meets the
requirements for an InternetProtocol
.
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { class tcp { public: // types: typedef basic_endpoint<tcp> endpoint; typedef basic_resolver<tcp> resolver; typedef basic_stream_socket<tcp> socket; typedef basic_socket_acceptor<tcp> acceptor; typedef basic_socket_iostream<tcp> iostream; class no_delay; // static members: static tcp v4(); static tcp v6(); private: tcp(); // not defined }; // tcp comparisons: bool operator==(const tcp& a, const tcp& b); bool operator!=(const tcp& a, const tcp& b); } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
Extensible implementations shall provide the following member functions:
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { class tcp { public: int family() const; int type() const; int protocol() const; // remainder unchanged }; } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
In the table below, u
denotes
an identifier.
Table 41. Behaviour of extensible implementations
expression |
value |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
[Note: The constants AF_INET
,
AF_INET6
and SOCK_STREAM
are defined in the POSIX
header file sys/socket.h
. The constant IPPROTO_TCP
is defined in the POSIX
header file netinet/in.h
.
—end note]
bool operator==(const tcp& a, const tcp& b);
Returns: A boolean indicating whether two objects of class
tcp
are equal, such that the expressiontcp::v4() == tcp::v4()
is true, the expressiontcp::v6() == tcp::v6()
is true, and the expressiontcp::v4() == tcp::v6()
is false.
bool operator!=(const tcp& a, const tcp& b);
Returns:
!(a == b)
.
The no_delay
class represents
a socket option for disabling the Nagle algorithm for coalescing small
segments. It shall be defined as a boolean
socket option with the name and values in the table below:
[Note: The constant IPPROTO_TCP
is defined in the POSIX header file netinet/in.h
.
The constant TCP_NODELAY
is defined in the POSIX header file netinet/tcp.h
. —end note]
The udp
class meets the
requirements for an InternetProtocol
.
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { class udp { public: // types: typedef basic_endpoint<udp> endpoint; typedef basic_resolver<udp> resolver; typedef basic_datagram_socket<udp> socket; // static members: static udp v4(); static udp v6(); private: udp(); // not defined }; // udp comparisons: bool operator==(const udp& a, const udp& b); bool operator!=(const udp& a, const udp& b); } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
Extensible implementations shall provide the following member functions:
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { class udp { public: int family() const; int type() const; int protocol() const; // remainder unchanged }; } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
In the table below, u
denotes
an identifier.
Table 43. Behaviour of extensible implementations
expression |
value |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
[Note: The constants AF_INET
,
AF_INET6
and SOCK_DGRAM
are defined in the POSIX
header file sys/socket.h
. The constant IPPROTO_UDP
is defined in the POSIX
header file netinet/in.h
.
—end note]
bool operator==(const udp& a, const udp& b);
Returns: A boolean indicating whether two objects of class
udp
are equal, such that the expressionudp::v4() == udp::v4()
is true, the expressionudp::v6() == udp::v6()
is true, and the expressionudp::v4() == udp::v6()
is false.
bool operator!=(const udp& a, const udp& b);
Returns:
!(a == b)
.
The v6_only
class represents
a socket option for determining whether a socket created for an IPv6 protocol
is restricted to IPv6 communications only. It shall be defined as a boolean socket option
with the name and values in the table below:
[Note: The constants IPPROTO_IPV6
and IPV6_V6ONLY
are defined
in the POSIX header file netinet/in.h
.
—end note]
The hops
class represents
a socket option for specifying the default number of hops (also known as
time-to-live or TTL) on outbound datagrams. It shall be defined as an
integral socket
option with the name and values in the table below:
Table 45. hops integral socket option
C |
L |
N |
---|---|---|
|
|
|
[Note: The constants IPPROTO_IP
,
IPPROTO_IPV6
and IPV6_UNICAST_HOPS
are defined in the
POSIX header file netinet/in.h
.
—end note]
Constructors for the hops
class shall throw out_of_range
if the argument is not in the range [0, 255]
.
The ip::multicast::join_group
and ip::multicast::leave_group
classes are socket options for multicast group management.
Multicast group management socket option classes satisfy the requirements
for CopyConstructible
,
Assignable
, and SettableSocketOption
.
[Example: Creating a UDP socket and joining a multicast group:
// Open an IPv4 UDP socket bound to a specific port. ip::udp::endpoint ep(ip::udp::v4(), 12345); ip::udp::socket sock(io_svc, ep); // Join a multicast group. ip::address addr = ip::address::from_string("239.255.0.1"); sock.set_option(ip::multicast::join_group(addr));
—end example]
Multicast group management socket option classes shall be defined as follows:
class C { public: // constructors: C(); explicit C(const address& multicast_group); explicit C(const address_v4& multicast_group, const address_v4& network_interface = address_v4::any()); explicit C(const address_v6& multicast_group, unsigned int network_interface = 0); };
Extensible implementations shall provide the following member functions:
class C { public: template<class Protocol> int level(const Protocol& p) const; template<class Protocol> int name(const Protocol& p) const; template<class Protocol> const unspecified* data(const Protocol& p) const; template<class Protocol> size_t size(const Protocol& p) const; // remainder unchanged private: //ip_mreq v4_value_; exposition only //ipv6_mreq v6_value_; exposition only };
The names and values used in the definition of the multicast group management socket option classes are described in the table below.
Table 46. Multicast group management socket options
C |
L |
N |
description |
---|---|---|---|
|
|
|
Used to join a multicast group. |
|
|
|
Used to leave a multicast group. |
[Note: The constants IPPROTO_IP
and IPPROTO_IPV6
are defined
in the POSIX header file netinet/in.h
.
The constants IPV6_JOIN_GROUP
and IPV6_LEAVE_GROUP
are
defined in the POSIX header file netinet/in.h
.
—end note]
C();
Effects: For extensible implementations, both
v4_value_
andv6_value_
are zero-initialized.
explicit C(const address& multicast_group);
Effects: For extensible implementations, if
multicast_group.is_v6()
is true thenv6_value_.ipv6mr_multiaddr
is initialized to correspond to the IPv6 address returned bymulticast_group.to_v6()
,v6_value_.ipv6mr_interface
is set to0
, andv4_value_
is zero-initialized; otherwise,v4_value_.imr_multiaddr
is initialized to correspond to the IPv4 address returned bymulticast_group.to_v4()
,v4_value_.imr_interface
is zero-initialized, andv6_value_
is zero-initialized.
explicit C(const address_v4& multicast_group, const address_v4& network_interface = address_v4::any());
Effects: For extensible implementations,
v4_value_.imr_multiaddr
is initialized to correspond to the addressmulticast_group
,v4_value_.imr_interface
is initialized to correspond to addressnetwork_interface
, andv6_value_
is zero-initialized.
explicit C(const address_v6& multicast_group, unsigned int network_interface = 0);
Effects: For extensible implementations,
v6_value_.ipv6mr_multiaddr
is initialized to correspond to the addressmulticast_group
,v6_value_.ipv6mr_interface
is initialized tonetwork_interface
, andv4_value_
is zero-initialized.
template<class Protocol> int level(const Protocol& p) const;
Returns:
L
.
template<class Protocol> int name(const Protocol& p) const;
Returns:
N
.
template<class Protocol> const unspecified* data(const Protocol& p) const;
Returns:
&v6_value_
ifp.family() == AF_INET6
, otherwise&v4_value_
.
template<class Protocol> size_t size(const Protocol& p) const;
Returns:
sizeof(v6_value_)
ifp.family() == AF_INET6
, otherwisesizeof(v4_value_)
.
The outbound_interface
class represents a socket option that specifies the network interface to
use for outgoing multicast datagrams.
outbound_interface
satisfies
the requirements for CopyConstructible
,
Assignable
, and SettableSocketOption
.
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { namespace multicast { class outbound_interface { public: // constructors: outbound_interface(); explicit outbound_interface(const address_v4& network_interface); explicit outbound_interface(unsigned int network_interface); }; } // namespace multicast } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
Extensible implementations shall provide the following member functions:
namespace std { namespace experimental { inline namespace network_v1 { namespace ip { namespace multicast { class outbound_interface { public: template<class Protocol> int level(const Protocol& p) const; template<class Protocol> int name(const Protocol& p) const; template<class Protocol> const unspecified* data(const Protocol& p) const; template<class Protocol> size_t size(const Protocol& p) const; // remainder unchanged private: // in_addr v4_value_; exposition only // unsigned int v6_value_; exposition only }; } // namespace multicast } // namespace ip } // inline namespace network_v1 } // namespace experimental } // namespace std
outbound_interface();
Effects: For extensible implementations, both
v4_value_
andv6_value_
are zero-initialized.
explicit outbound_interface(const address_v4& network_interface);
Effects: For extensible implementations,
v4_value_
is initialized to correspond to the IPv4 addressnetwork_interface
, andv6_value_
is zero-initialized.
explicit outbound_interface(unsigned int network_interface);
Effects: For extensible implementations,
v6_value_
is initialized tonetwork_interface
, andv4_value_
is zero-initialized.
template<class Protocol> int level(const Protocol& p) const;
Returns:
IPPROTO_IPV6
ifp.family() == AF_INET6
, otherwiseIPPROTO_IP
.
[Note: The constants
IPPROTO_IP
andIPPROTO_IPV6
are defined in the POSIX header filenetinet/in.h
. —end note]
template<class Protocol> int name(const Protocol& p) const;
Returns:
IPV6_MULTICAST_IF
ifp.family() == AF_INET6
, otherwiseIP_MULTICAST_IF
.
[Note: The constant
IPV6_MULTICAST_IF
is defined in the POSIX header filenetinet/in.h
. —end note]
template<class Protocol> const unspecified* data(const Protocol& p) const;
Returns:
&v6_value_
ifp.family() == AF_INET6
, otherwise&v4_value_
.
template<class Protocol> size_t size(const Protocol& p) const;
Returns:
sizeof(v6_value_)
ifp.family() == AF_INET6
, otherwisesizeof(v4_value_)
.
The hops
class represents
a socket option for specifying the default number of hops (also known as
time-to-live or TTL) on outbound multicast datagrams. It shall be defined
as an integral
socket option with the name and values in the table below:
Table 47. hops integral socket option
C |
L |
N |
---|---|---|
|
|
|
[Note: The constants IPPROTO_IP
,
IPPROTO_IPV6
and IPV6_MULTICAST_HOPS
are defined in the
POSIX header file netinet/in.h
.
—end note]
Constructors for the hops
class shall throw out_of_range
if the argument is not in the range [0, 255]
.
The enable_loopback
class
represents a socket option for determining whether multicast datagrams
are delivered back to the local application. It shall be defined as a
boolean socket
option with the name and values in the table below:
Table 48. enable_loopback boolean socket option
C |
L |
N |
---|---|---|
|
|
|
[Note: The constants IPPROTO_IP
,
IPPROTO_IPV6
and IPV6_MULTICAST_LOOP
are defined in the
POSIX header file netinet/in.h
.
—end note]
In the eleven years since Asio's inception, hundreds of people have contributed to its development through design review, patches, feature suggestions, bug reports, and usage feedback from the field. With respect to the 2014 refresh of the Networking Library Proposal, the author would particularly like to thank Jamie Allsop for providing feedback during the drafting process, and Oliver Kowalke for contributing towards the design and implementation of the CIDR support.
[POSIX] ISO/IEC 9945:2003, IEEE Std 1003.1-2001, and The Open Group Base Specifications, Issue 6. Also known as The Single Unix Specification, Version 3.
[N4045] Kohlhoff, Christopher, Library Foundations for Asynchronous Operations, Revision 2, 2014.
[N4046] Kohlhoff, Christopher, Executors and Asynchronous Operations, 2014.
[N4099] Draft Filesystem Technical Specification, 2014.
[ACE] Schmidt, Douglas C., ADAPTIVE Communication Environment, http://www.cs.wustl.edu/~schmidt/ACE.html.
[SYMBIAN] Symbian Ltd, Sockets Client, http://www.symbian.com/developer/techlib/v70sdocs/doc_source/reference/cpp/SocketsClient/index.html.
[MS-NET] Microsoft Corporation, .NET Framework Class Library, Socket Class, http://msdn2.microsoft.com/en-us/library/system.net.sockets.socket.aspx.
[ES-API] The Interconnect Software Consortium / The Open Group, Extended Sockets API (ES-API), Issue 1.0, 2005, http://opengroup.org/icsc/uploads/40/6415/ES_API_1_0.pdf.
[UNPV1] Stevens, W. Richard, UNIX Network Programming, Volume 1, 2nd Edition, Prentice Hall, 1998.
[POSA2] Schmidt, Douglas C. et al, Pattern Oriented Software Architecture, Volume 2, Wiley, 2000.
[RFC821] Postel, J., RFC 821: Simple Mail Transfer Protocol, 1982, http://www.ietf.org/rfc/rfc0821.txt.
[RFC959] Postel, J. and Reynolds, J., RFC 959: File Transfer Protocol (FTP), 1985, http://www.ietf.org/rfc/rfc0959.txt.
[RFC2616] Fielding, R. et al, RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1, 1999, http://www.ietf.org/rfc/rfc2616.txt.
[RFC2732] Hinden, R., Carpenter, B. and Masinter, L., RFC 2732: Format for Literal IPv6 Addresses in URL's, 1999, http://www.ietf.org/rfc/rfc2732.txt.
[RFC3513] Hinden, R. and Deering, S., RFC 3513: Internet Protocol Version 6 (IPv6) Addressing Architecture, 2003, http://www.ietf.org/rfc/rfc3513.txt.