Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / asio / doc / requirements / asynchronous_operations.qbk
1 [/
2  / Copyright (c) 2003-2019 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 This section uses the names `Alloc1`, `Alloc2`, `alloc1`, `alloc2`, `Args`,
11 `CompletionHandler`, `completion_handler`, `Executor1`, `Executor2`, `ex1`,
12 `ex2`, `f`, [^['i]], [^['N]], `Signature`, `token`, [^T[sub ['i]]], [^t[sub
13 ['i]]], `work1`, and `work2` as placeholders for specifying the requirements
14 below.
15
16 [heading General asynchronous operation concepts]
17
18 An ['initiating function] is a function which may be called to start an
19 asynchronous operation. A ['completion handler] is a function object that will
20 be invoked, at most once, with the result of the asynchronous operation.
21
22 The lifecycle of an asynchronous operation is comprised of the following events
23 and phases:
24
25 [mdash] Event 1: The asynchronous operation is started by a call to the
26 initiating function.
27
28 [mdash] Phase 1: The asynchronous operation is now ['outstanding].
29
30 [mdash] Event 2: The externally observable side effects of the asynchronous
31 operation, if any, are fully established. The completion handler is submitted
32 to an executor.
33
34 [mdash] Phase 2: The asynchronous operation is now ['completed].
35
36 [mdash] Event 3: The completion handler is called with the result of the
37 asynchronous operation.
38
39 In this library, all functions with the prefix `async_` are initiating
40 functions.
41
42 [heading Completion tokens and handlers]
43
44 Initiating functions:
45
46 [mdash] are function templates with template parameter `CompletionToken`;
47
48 [mdash] accept, as the final parameter, a ['completion token] object `token`
49 of type `CompletionToken`;
50
51 [mdash] specify a ['completion signature], which is a call signature (C++Std
52 [func.def]) `Signature` that determines the arguments to the completion
53 handler.
54
55 An initiating function determines the type `CompletionHandler` of its
56 completion handler function object by performing `typename
57 async_result<decay_t<CompletionToken>, Signature>::completion_handler_type`.
58 The completion handler object `completion_handler` is initialized with
59 `forward<CompletionToken>(token)`. [inline_note No other requirements are
60 placed on the type `CompletionToken`.]
61
62 The type `CompletionHandler` must satisfy the requirements of `Destructible`
63 (C++Std [destructible]) and `MoveConstructible` (C++Std
64 [moveconstructible]), and be callable with the specified call signature.
65
66 In this library, all initiating functions specify a ['Completion signature]
67 element that defines the call signature `Signature`. The ['Completion
68 signature] elements in this Technical Specification have named parameters, and
69 the results of an asynchronous operation are specified in terms of these names.
70
71 [heading Automatic deduction of initiating function return type]
72
73 The return type of an initiating function is `typename
74 async_result<decay_t<CompletionToken>, Signature>::return_type`.
75
76 For the sake of exposition, this library sometimes annotates functions with a
77 return type ['[^DEDUCED]]. For every function declaration that returns
78 ['[^DEDUCED]], the meaning is equivalent to specifying the return type as
79 `typename async_result<decay_t<CompletionToken>, Signature>::return_type`.
80
81 [heading Production of initiating function return value]
82
83 An initiating function produces its return type as follows:
84
85 [mdash] constructing an object `result` of type
86 `async_result<decay_t<CompletionToken>, Signature>`, initialized as
87 `result(completion_handler)`; and
88
89 [mdash] using `result.get()` as the operand of the return statement.
90
91 \[['Example:] Given an asynchronous operation with ['Completion signature]
92 `void(R1 r1, R2 r2)`, an initiating function meeting these requirements may be
93 implemented as follows:
94
95   template<class CompletionToken>
96   auto async_xyz(T1 t1, T2 t2, CompletionToken&& token)
97   {
98     typename async_result<decay_t<CompletionToken>, void(R1, R2)>::completion_handler_type
99       completion_handler(forward<CompletionToken>(token));
100
101     async_result<decay_t<CompletionToken>, void(R1, R2)> result(completion_handler);
102
103     // initiate the operation and cause completion_handler to be invoked with
104     // the result
105
106     return result.get();
107   }
108
109 For convenience, initiating functions may be implemented using the
110 `async_completion` template:
111
112   template<class CompletionToken>
113   auto async_xyz(T1 t1, T2 t2, CompletionToken&& token)
114   {
115     async_completion<CompletionToken, void(R1, R2)> init(token);
116
117     // initiate the operation and cause init.completion_handler to be invoked
118     // with the result
119
120     return init.result.get();
121   }
122
123 '''&mdash;'''['end example]\]
124
125 [heading Lifetime of initiating function arguments]
126
127 Unless otherwise specified, the lifetime of arguments to initiating functions
128 shall be treated as follows:
129
130 [mdash] If the parameter has a pointer type or has a type of lvalue reference
131 to non-const, the implementation may assume the validity of the pointee or
132 referent, respectively, until the completion handler is invoked. [inline_note
133 In other words, the program must guarantee the validity of the argument until
134 the completion handler is invoked.]
135
136 [mdash] Otherwise, the implementation must not assume the validity of the
137 argument after the initiating function completes. [inline_note In other words,
138 the program is not required to guarantee the validity of the argument after the
139 initiating function completes.] The implementation may make copies of the
140 argument, and all copies shall be destroyed no later than immediately after
141 invocation of the completion handler.
142
143 [heading Non-blocking requirements on initiating functions]
144
145 An initiating function shall not block (C++Std [defns.block]) the calling
146 thread pending completion of the outstanding operation.
147
148 [std_note Initiating functions may still block the calling thread for other
149 reasons. For example, an initiating function may lock a mutex in order to
150 synchronize access to shared data.]
151
152 [heading Associated executor]
153
154 Certain objects that participate in asynchronous operations have an
155 ['associated executor]. These are obtained as specified in the sections below.
156
157 [heading Associated I/O executor]
158
159 An asynchronous operation has an associated executor satisfying the [link
160 boost_asio.reference.Executor1 `Executor`] requirements. If not otherwise specified by
161 the asynchronous operation, this associated executor is an object of type
162 `system_executor`.
163
164 All asynchronous operations in this library have an associated executor object
165 that is determined as follows:
166
167 [mdash] If the initiating function is a member function, the associated
168 executor is that returned by the `get_executor` member function on the same
169 object.
170
171 [mdash] If the initiating function is not a member function, the associated
172 executor is that returned by the `get_executor` member function of the first
173 argument to the initiating function.
174
175 Let `Executor1` be the type of the associated executor. Let `ex1` be a value of
176 type `Executor1`, representing the associated executor object obtained as
177 described above.
178
179 [heading Associated completion handler executor]
180
181 A completion handler object of type `CompletionHandler` has an associated
182 executor of type `Executor2` satisfying the [link boost_asio.reference.Executor1
183 Executor requirements]. The type `Executor2` is
184 `associated_executor_t<CompletionHandler, Executor1>`. Let `ex2` be a value of
185 type `Executor2` obtained by performing
186 `get_associated_executor(completion_handler, ex1)`.
187
188 [heading Outstanding work]
189
190 Until the asynchronous operation has completed, the asynchronous operation
191 shall maintain:
192
193 [mdash] an object `work1` of type `executor_work_guard<Executor1>`, initialized
194 as `work1(ex1)`, and where `work1.owns_work() == true`; and
195
196 [mdash] an object `work2` of type `executor_work_guard<Executor2>`, initialized
197 as `work2(ex2)`, and where `work2.owns_work() == true`.
198
199 [heading Allocation of intermediate storage]
200
201 Asynchronous operations may allocate memory. [inline_note Such as a data
202 structure to store copies of the `completion_handler` object and the initiating
203 function's arguments.]
204
205 Let `Alloc1` be a type, satisfying the [link boost_asio.reference.ProtoAllocator
206 `ProtoAllocator`] requirements, that represents the asynchronous operation's
207 default allocation strategy. [inline_note Typically `std::allocator<void>`.]
208 Let `alloc1` be a value of type `Alloc1`.
209
210 A completion handler object of type `CompletionHandler` has an associated
211 allocator object `alloc2` of type `Alloc2` satisfying the [link
212 boost_asio.reference.ProtoAllocator `ProtoAllocator`] requirements. The type `Alloc2`
213 is `associated_allocator_t<CompletionHandler, Alloc1>`. Let `alloc2` be a value
214 of type `Alloc2` obtained by performing
215 `get_associated_allocator(completion_handler, alloc1)`.
216
217 The asynchronous operations defined in this library:
218
219 [mdash] If required, allocate memory using only the completion handler's
220 associated allocator.
221
222 [mdash] Prior to completion handler execution, deallocate any memory allocated
223 using the completion handler's associated allocator.
224
225 [std_note The implementation may perform operating system or underlying API
226 calls that perform memory allocations not using the associated allocator.
227 Invocations of the allocator functions may not introduce data races (See C++Std
228 \[res.on.data.races\]).]
229
230 [heading Execution of completion handler on completion of asynchronous operation]
231
232 Let `Args...` be the argument types of the completion signature `Signature` and
233 let [^['N]] be `sizeof...(Args)`. Let [^['i]] be in the range [half_open_range
234 `0`,[^['N]]]. Let [^T[sub ['i]]] be the [^['i]]th type in `Args...` and let
235 [^t[sub ['i]]] be the [^['i]]th completion handler argument associated with
236 [^T[sub ['i]]].
237
238 Let `f` be a function object, callable as `f()`, that invokes
239 `completion_handler` as if by [^completion_handler(forward<T[sub ['0]]>(t[sub
240 ['0]]), ..., forward<T[sub ['N-1]]>(t[sub ['N-1]]))].
241
242 If an asynchonous operation completes immediately (that is, within the thread
243 of execution calling the initiating function, and before the initiating
244 function returns), the completion handler shall be submitted for execution as
245 if by performing `ex2.post(std::move(f), alloc2)`. Otherwise, the completion
246 handler shall be submitted for execution as if by performing
247 `ex2.dispatch(std::move(f), alloc2)`.
248
249 [heading Completion handlers and exceptions]
250
251 Completion handlers are permitted to throw exceptions. The effect of any
252 exception propagated from the execution of a completion handler is determined
253 by the executor which is executing the completion handler.
254
255 [heading Default completion tokens]
256
257 Every I/O executor type has an associated default completion token type. This is
258 specified via the `default_completion_token` trait. This trait may be used in
259 asynchronous operation declarations as follows:
260
261   template <
262       typename IoObject,
263       typename CompletionToken =
264         typename default_completion_token<
265           typename IoObject::executor_type
266         >::type
267     >
268   auto async_xyz(
269       IoObject& io_object,
270       CompletionToken&& token =
271         typename default_completion_token<
272           typename IoObject::executor_type
273         >::type{}
274     );
275
276 If not specialised, this trait type is `void`, meaning no default completion
277 token type is available for the given I/O executor.
278
279 \[['Example:] The `default_completion_token` trait is specialised for the
280 `use_awaitable` completion token so that it may be used as shown in the
281 following example:
282
283   auto socket = use_awaitable.as_default_on(tcp::socket(my_context));
284   // ...
285   co_await socket.async_connect(my_endpoint); // Defaults to use_awaitable.
286
287 In this example, the type of the `socket` object is transformed from
288 `tcp::socket` to have an I/O executor with the default completion token set to
289 `use_awaitable`.
290
291 Alternatively, the socket type may be computed directly:
292
293   using tcp_socket = use_awaitable_t<>::as_default_on_t<tcp::socket>;
294   tcp_socket socket(my_context);
295   // ...
296   co_await socket.async_connect(my_endpoint); // Defaults to use_awaitable.
297
298 '''&mdash;'''['end example]\]
299
300 [endsect]