]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/asio/doc/requirements/asynchronous_operations.qbk
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / asio / doc / requirements / asynchronous_operations.qbk
1 [/
2 / Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
3 /
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)
6 /]
7
8 [section:asynchronous_operations Requirements on asynchronous operations]
9
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].
13
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
17 error_code`.
18
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
24 false.
25
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.
32
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`).
38
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.
45
46 Arguments to initiating functions will be treated as follows:
47
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.
53
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.
57
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:
61
62 [mdash] The thread is executing any member function of the associated
63 `io_service` object.
64
65 [mdash] The thread is executing the destructor of the associated `io_service`
66 object.
67
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.
71
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.
75
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.
79
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
85 from the one thread.]
86
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.
91
92 When an asynchronous operation is complete, the handler for the operation will
93 be invoked as if by:
94
95 # Constructing a bound completion handler `bch` for the handler, as described
96 below.
97
98 # Calling `ios.post(bch)` to schedule the handler for deferred invocation,
99 where `ios` is the associated `io_service`.
100
101 This implies that the handler must not be called directly from within
102 the initiating function, even if the asynchronous operation completes
103 immediately.
104
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].
114
115 For example, a bound completion handler for a `ReadHandler` may be implemented
116 as follows:
117
118 template<class ReadHandler>
119 struct bound_read_handler
120 {
121 bound_read_handler(ReadHandler handler, const error_code& ec, size_t s)
122 : handler_(handler), ec_(ec), s_(s)
123 {
124 }
125
126 void operator()()
127 {
128 handler_(ec_, s_);
129 }
130
131 ReadHandler handler_;
132 const error_code ec_;
133 const size_t s_;
134 };
135
136 template<class ReadHandler>
137 void* asio_handler_allocate(size_t size,
138 bound_read_handler<ReadHandler>* this_handler)
139 {
140 using boost::asio::asio_handler_allocate;
141 return asio_handler_allocate(size, &this_handler->handler_);
142 }
143
144 template<class ReadHandler>
145 void asio_handler_deallocate(void* pointer, std::size_t size,
146 bound_read_handler<ReadHandler>* this_handler)
147 {
148 using boost::asio::asio_handler_deallocate;
149 asio_handler_deallocate(pointer, size, &this_handler->handler_);
150 }
151
152 template<class F, class ReadHandler>
153 void asio_handler_invoke(const F& f,
154 bound_read_handler<ReadHandler>* this_handler)
155 {
156 using boost::asio::asio_handler_invoke;
157 asio_handler_invoke(f, &this_handler->handler_);
158 }
159
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.
164
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.
175
176 [heading Return type of an initiating function]
177
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`.
181
182 For other types, the return type may be customised via a two-step process:
183
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.
187
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.
191
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`
194 class.
195
196 As an example, consider what happens when enabling `std::future` support by
197 using the `boost::asio::use_future` special value, as in:
198
199 std::future<std::size_t> length =
200 my_socket.async_read_some(my_buffer, boost::asio::use_future);
201
202 When a handler signature has the form:
203
204 void handler(error_code ec, result_type result);
205
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.
210
211 Where a handler signature has the form:
212
213 void handler(error_code ec);
214
215 the initiating function instead returns `std::future<void>`.
216
217 [endsect]