2 / Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
4 / Distributed under the Boost Software License, Version 1.0. (See accompanying
5 / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 [section:asynchronous_operations Requirements on asynchronous operations]
10 In Boost.Asio, an asynchronous operation is initiated by a function that is
11 named with the prefix `async_`. These functions will be referred to as
12 ['initiating functions].
14 All initiating functions in Boost.Asio take a function object meeting [link
15 boost_asio.reference.Handler handler] requirements as the final parameter.
16 These handlers accept as their first parameter an lvalue of type `const
19 Implementations of asynchronous operations in Boost.Asio may call the
20 application programming interface (API) provided by the operating system. If
21 such an operating system API call results in an error, the handler will be
22 invoked with a `const error_code` lvalue that evaluates to true. Otherwise the
23 handler will be invoked with a `const error_code` lvalue that evaluates to
26 Unless otherwise noted, when the behaviour of an asynchronous operation is
27 defined "as if" implemented by a __POSIX__ function, the handler will be
28 invoked with a value of type `error_code` that corresponds to the failure
29 condition described by __POSIX__ for that function, if any. Otherwise the
30 handler will be invoked with an implementation-defined `error_code` value that
31 reflects the operating system error.
33 Asynchronous operations will not fail with an error condition that indicates
34 interruption by a signal (__POSIX__ `EINTR`). Asynchronous operations will not
35 fail with any error condition associated with non-blocking operations
36 (__POSIX__ `EWOULDBLOCK`, `EAGAIN` or `EINPROGRESS`; __Windows__
37 `WSAEWOULDBLOCK` or `WSAEINPROGRESS`).
39 All asynchronous operations have an associated `io_service` object. Where the
40 initiating function is a member function, the associated `io_service` is that
41 returned by the `get_io_service()` member function on the same object. Where the
42 initiating function is not a member function, the associated `io_service` is
43 that returned by the `get_io_service()` member function of the first argument to
44 the initiating function.
46 Arguments to initiating functions will be treated as follows:
48 [mdash] If the parameter is declared as a const reference or by-value, the
49 program is not required to guarantee the validity of the argument after the
50 initiating function completes. The implementation may make copies of the
51 argument, and all copies will be destroyed no later than immediately after
52 invocation of the handler.
54 [mdash] If the parameter is declared as a non-const reference, const pointer or
55 non-const pointer, the program must guarantee the validity of the argument
56 until the handler is invoked.
58 The library implementation is only permitted to make calls to an initiating
59 function's arguments' copy constructors or destructors from a thread that
60 satisfies one of the following conditions:
62 [mdash] The thread is executing any member function of the associated
65 [mdash] The thread is executing the destructor of the associated `io_service`
68 [mdash] The thread is executing one of the `io_service` service access
69 functions `use_service`, `add_service` or `has_service`, where the first
70 argument is the associated `io_service` object.
72 [mdash] The thread is executing any member function, constructor or destructor
73 of an object of a class defined in this clause, where the object's
74 `get_io_service()` member function returns the associated `io_service` object.
76 [mdash] The thread is executing any function defined in this clause, where any
77 argument to the function has an `get_io_service()` member function that returns
78 the associated `io_service` object.
80 [blurb Boost.Asio may use one or more hidden threads to emulate asynchronous
81 functionality. The above requirements are intended to prevent these hidden
82 threads from making calls to program code. This means that a program can, for
83 example, use thread-unsafe reference counting in handler objects, provided the
84 program ensures that all calls to an `io_service` and related objects occur
87 The `io_service` object associated with an asynchronous operation will have
88 unfinished work, as if by maintaining the existence of one or more objects of
89 class `io_service::work` constructed using the `io_service`, until immediately
90 after the handler for the asynchronous operation has been invoked.
92 When an asynchronous operation is complete, the handler for the operation will
95 # Constructing a bound completion handler `bch` for the handler, as described
98 # Calling `ios.post(bch)` to schedule the handler for deferred invocation,
99 where `ios` is the associated `io_service`.
101 This implies that the handler must not be called directly from within
102 the initiating function, even if the asynchronous operation completes
105 A bound completion handler is a handler object that contains a copy of a
106 user-supplied handler, where the user-supplied handler accepts one or more
107 arguments. The bound completion handler does not accept any arguments, and
108 contains values to be passed as arguments to the user-supplied handler. The
109 bound completion handler forwards the `asio_handler_allocate()`,
110 `asio_handler_deallocate()`, and `asio_handler_invoke()` calls to the
111 corresponding functions for the user-supplied handler. A bound completion
112 handler meets the requirements for a [link
113 boost_asio.reference.CompletionHandler completion handler].
115 For example, a bound completion handler for a `ReadHandler` may be implemented
118 template<class ReadHandler>
119 struct bound_read_handler
121 bound_read_handler(ReadHandler handler, const error_code& ec, size_t s)
122 : handler_(handler), ec_(ec), s_(s)
131 ReadHandler handler_;
132 const error_code ec_;
136 template<class ReadHandler>
137 void* asio_handler_allocate(size_t size,
138 bound_read_handler<ReadHandler>* this_handler)
140 using boost::asio::asio_handler_allocate;
141 return asio_handler_allocate(size, &this_handler->handler_);
144 template<class ReadHandler>
145 void asio_handler_deallocate(void* pointer, std::size_t size,
146 bound_read_handler<ReadHandler>* this_handler)
148 using boost::asio::asio_handler_deallocate;
149 asio_handler_deallocate(pointer, size, &this_handler->handler_);
152 template<class F, class ReadHandler>
153 void asio_handler_invoke(const F& f,
154 bound_read_handler<ReadHandler>* this_handler)
156 using boost::asio::asio_handler_invoke;
157 asio_handler_invoke(f, &this_handler->handler_);
160 If the thread that initiates an asynchronous operation terminates before the
161 associated handler is invoked, the behaviour is implementation-defined.
162 Specifically, on __Windows__ versions prior to Vista, unfinished operations are
163 cancelled when the initiating thread exits.
165 The handler argument to an initiating function defines a handler identity. That
166 is, the original handler argument and any copies of the handler argument will
167 be considered equivalent. If the implementation needs to allocate storage for
168 an asynchronous operation, the implementation will perform
169 `asio_handler_allocate(size, &h)`, where `size` is the required size in bytes,
170 and `h` is the handler. The implementation will perform
171 `asio_handler_deallocate(p, size, &h)`, where `p` is a pointer to the storage,
172 to deallocate the storage prior to the invocation of the handler via
173 `asio_handler_invoke`. Multiple storage blocks may be allocated for a single
174 asynchronous operation.
176 [heading Return type of an initiating function]
178 By default, initiating functions return `void`. This is always the case when
179 the handler is a function pointer, C++11 lambda, or a function object produced
180 by `boost::bind` or `std::bind`.
182 For other types, the return type may be customised via a two-step process:
184 # A specialisation of the [link boost_asio.reference.handler_type `handler_type`]
185 template, which is used to determine the true handler type based on the
186 asynchronous operation's handler's signature.
188 # A specialisation of the [link boost_asio.reference.async_result `async_result`]
189 template, which is used both to determine the return type and to extract the
190 return value from the handler.
192 These two templates have been specialised to provide support for [link
193 boost_asio.overview.core.spawn stackful coroutines] and the C++11 `std::future`
196 As an example, consider what happens when enabling `std::future` support by
197 using the `boost::asio::use_future` special value, as in:
199 std::future<std::size_t> length =
200 my_socket.async_read_some(my_buffer, boost::asio::use_future);
202 When a handler signature has the form:
204 void handler(error_code ec, result_type result);
206 the initiating function returns a `std::future` templated on `result_type`. In
207 the above `async_read_some` example, this is `std::size_t`. If the asynchronous
208 operation fails, the `error_code` is converted into a `system_error` exception
209 and passed back to the caller through the future.
211 Where a handler signature has the form:
213 void handler(error_code ec);
215 the initiating function instead returns `std::future<void>`.