]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | // |
2 | // io_context.hpp | |
3 | // ~~~~~~~~~~~~~~ | |
4 | // | |
1e59de90 | 5 | // Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
b32b8144 FG |
6 | // |
7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
9 | // | |
10 | ||
11 | #ifndef BOOST_ASIO_IO_CONTEXT_HPP | |
12 | #define BOOST_ASIO_IO_CONTEXT_HPP | |
13 | ||
14 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) | |
15 | # pragma once | |
16 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) | |
17 | ||
18 | #include <boost/asio/detail/config.hpp> | |
19 | #include <cstddef> | |
20 | #include <stdexcept> | |
21 | #include <typeinfo> | |
22 | #include <boost/asio/async_result.hpp> | |
1e59de90 TL |
23 | #include <boost/asio/detail/concurrency_hint.hpp> |
24 | #include <boost/asio/detail/cstdint.hpp> | |
b32b8144 FG |
25 | #include <boost/asio/detail/wrapped_handler.hpp> |
26 | #include <boost/system/error_code.hpp> | |
20effc67 | 27 | #include <boost/asio/execution.hpp> |
b32b8144 FG |
28 | #include <boost/asio/execution_context.hpp> |
29 | ||
30 | #if defined(BOOST_ASIO_HAS_CHRONO) | |
31 | # include <boost/asio/detail/chrono.hpp> | |
32 | #endif // defined(BOOST_ASIO_HAS_CHRONO) | |
33 | ||
34 | #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) | |
35 | # include <boost/asio/detail/winsock_init.hpp> | |
36 | #elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \ | |
37 | || defined(__osf__) | |
38 | # include <boost/asio/detail/signal_init.hpp> | |
39 | #endif | |
40 | ||
20effc67 TL |
41 | #if defined(BOOST_ASIO_HAS_IOCP) |
42 | # include <boost/asio/detail/win_iocp_io_context.hpp> | |
43 | #else | |
44 | # include <boost/asio/detail/scheduler.hpp> | |
45 | #endif | |
46 | ||
b32b8144 FG |
47 | #include <boost/asio/detail/push_options.hpp> |
48 | ||
49 | namespace boost { | |
50 | namespace asio { | |
51 | ||
52 | namespace detail { | |
53 | #if defined(BOOST_ASIO_HAS_IOCP) | |
20effc67 | 54 | typedef win_iocp_io_context io_context_impl; |
b32b8144 FG |
55 | class win_iocp_overlapped_ptr; |
56 | #else | |
20effc67 | 57 | typedef scheduler io_context_impl; |
b32b8144 | 58 | #endif |
20effc67 TL |
59 | |
60 | struct io_context_bits | |
61 | { | |
1e59de90 TL |
62 | BOOST_ASIO_STATIC_CONSTEXPR(uintptr_t, blocking_never = 1); |
63 | BOOST_ASIO_STATIC_CONSTEXPR(uintptr_t, relationship_continuation = 2); | |
64 | BOOST_ASIO_STATIC_CONSTEXPR(uintptr_t, outstanding_work_tracked = 4); | |
65 | BOOST_ASIO_STATIC_CONSTEXPR(uintptr_t, runtime_bits = 3); | |
20effc67 | 66 | }; |
b32b8144 FG |
67 | } // namespace detail |
68 | ||
69 | /// Provides core I/O functionality. | |
70 | /** | |
71 | * The io_context class provides the core I/O functionality for users of the | |
72 | * asynchronous I/O objects, including: | |
73 | * | |
74 | * @li boost::asio::ip::tcp::socket | |
75 | * @li boost::asio::ip::tcp::acceptor | |
76 | * @li boost::asio::ip::udp::socket | |
77 | * @li boost::asio::deadline_timer. | |
78 | * | |
79 | * The io_context class also includes facilities intended for developers of | |
80 | * custom asynchronous services. | |
81 | * | |
82 | * @par Thread Safety | |
83 | * @e Distinct @e objects: Safe.@n | |
84 | * @e Shared @e objects: Safe, with the specific exceptions of the restart() | |
85 | * and notify_fork() functions. Calling restart() while there are unfinished | |
86 | * run(), run_one(), run_for(), run_until(), poll() or poll_one() calls results | |
87 | * in undefined behaviour. The notify_fork() function should not be called | |
88 | * while any io_context function, or any function on an I/O object that is | |
89 | * associated with the io_context, is being called in another thread. | |
90 | * | |
91 | * @par Concepts: | |
92 | * Dispatcher. | |
93 | * | |
94 | * @par Synchronous and asynchronous operations | |
95 | * | |
96 | * Synchronous operations on I/O objects implicitly run the io_context object | |
97 | * for an individual operation. The io_context functions run(), run_one(), | |
98 | * run_for(), run_until(), poll() or poll_one() must be called for the | |
99 | * io_context to perform asynchronous operations on behalf of a C++ program. | |
100 | * Notification that an asynchronous operation has completed is delivered by | |
101 | * invocation of the associated handler. Handlers are invoked only by a thread | |
102 | * that is currently calling any overload of run(), run_one(), run_for(), | |
103 | * run_until(), poll() or poll_one() for the io_context. | |
104 | * | |
105 | * @par Effect of exceptions thrown from handlers | |
106 | * | |
107 | * If an exception is thrown from a handler, the exception is allowed to | |
108 | * propagate through the throwing thread's invocation of run(), run_one(), | |
109 | * run_for(), run_until(), poll() or poll_one(). No other threads that are | |
110 | * calling any of these functions are affected. It is then the responsibility | |
111 | * of the application to catch the exception. | |
112 | * | |
113 | * After the exception has been caught, the run(), run_one(), run_for(), | |
114 | * run_until(), poll() or poll_one() call may be restarted @em without the need | |
115 | * for an intervening call to restart(). This allows the thread to rejoin the | |
116 | * io_context object's thread pool without impacting any other threads in the | |
117 | * pool. | |
118 | * | |
119 | * For example: | |
120 | * | |
121 | * @code | |
122 | * boost::asio::io_context io_context; | |
123 | * ... | |
124 | * for (;;) | |
125 | * { | |
126 | * try | |
127 | * { | |
128 | * io_context.run(); | |
129 | * break; // run() exited normally | |
130 | * } | |
131 | * catch (my_exception& e) | |
132 | * { | |
133 | * // Deal with exception as appropriate. | |
134 | * } | |
135 | * } | |
136 | * @endcode | |
137 | * | |
138 | * @par Submitting arbitrary tasks to the io_context | |
139 | * | |
140 | * To submit functions to the io_context, use the @ref boost::asio::dispatch, | |
141 | * @ref boost::asio::post or @ref boost::asio::defer free functions. | |
142 | * | |
143 | * For example: | |
144 | * | |
145 | * @code void my_task() | |
146 | * { | |
147 | * ... | |
148 | * } | |
149 | * | |
150 | * ... | |
151 | * | |
152 | * boost::asio::io_context io_context; | |
153 | * | |
154 | * // Submit a function to the io_context. | |
155 | * boost::asio::post(io_context, my_task); | |
156 | * | |
157 | * // Submit a lambda object to the io_context. | |
158 | * boost::asio::post(io_context, | |
159 | * []() | |
160 | * { | |
161 | * ... | |
162 | * }); | |
163 | * | |
164 | * // Run the io_context until it runs out of work. | |
165 | * io_context.run(); @endcode | |
166 | * | |
167 | * @par Stopping the io_context from running out of work | |
168 | * | |
169 | * Some applications may need to prevent an io_context object's run() call from | |
170 | * returning when there is no more work to do. For example, the io_context may | |
171 | * be being run in a background thread that is launched prior to the | |
172 | * application's asynchronous operations. The run() call may be kept running by | |
1e59de90 TL |
173 | * using the @ref make_work_guard function to create an object of type |
174 | * boost::asio::executor_work_guard<io_context::executor_type>: | |
b32b8144 FG |
175 | * |
176 | * @code boost::asio::io_context io_context; | |
1e59de90 TL |
177 | * boost::asio::executor_work_guard<boost::asio::io_context::executor_type> |
178 | * = boost::asio::make_work_guard(io_context); | |
b32b8144 FG |
179 | * ... @endcode |
180 | * | |
181 | * To effect a shutdown, the application will then need to call the io_context | |
182 | * object's stop() member function. This will cause the io_context run() call | |
183 | * to return as soon as possible, abandoning unfinished operations and without | |
184 | * permitting ready handlers to be dispatched. | |
185 | * | |
186 | * Alternatively, if the application requires that all operations and handlers | |
1e59de90 | 187 | * be allowed to finish normally, the work object may be explicitly reset. |
b32b8144 FG |
188 | * |
189 | * @code boost::asio::io_context io_context; | |
1e59de90 TL |
190 | * boost::asio::executor_work_guard<boost::asio::io_context::executor_type> |
191 | * = boost::asio::make_work_guard(io_context); | |
b32b8144 | 192 | * ... |
1e59de90 | 193 | * work.reset(); // Allow run() to exit. @endcode |
b32b8144 FG |
194 | */ |
195 | class io_context | |
196 | : public execution_context | |
197 | { | |
198 | private: | |
199 | typedef detail::io_context_impl impl_type; | |
200 | #if defined(BOOST_ASIO_HAS_IOCP) | |
201 | friend class detail::win_iocp_overlapped_ptr; | |
202 | #endif | |
203 | ||
204 | public: | |
1e59de90 | 205 | template <typename Allocator, uintptr_t Bits> |
20effc67 TL |
206 | class basic_executor_type; |
207 | ||
1e59de90 | 208 | template <typename Allocator, uintptr_t Bits> |
20effc67 TL |
209 | friend class basic_executor_type; |
210 | ||
211 | /// Executor used to submit functions to an io_context. | |
212 | typedef basic_executor_type<std::allocator<void>, 0> executor_type; | |
b32b8144 FG |
213 | |
214 | #if !defined(BOOST_ASIO_NO_DEPRECATED) | |
215 | class work; | |
216 | friend class work; | |
217 | #endif // !defined(BOOST_ASIO_NO_DEPRECATED) | |
218 | ||
219 | class service; | |
220 | ||
20effc67 TL |
221 | #if !defined(BOOST_ASIO_NO_EXTENSIONS) \ |
222 | && !defined(BOOST_ASIO_NO_TS_EXECUTORS) | |
b32b8144 FG |
223 | class strand; |
224 | #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) | |
20effc67 | 225 | // && !defined(BOOST_ASIO_NO_TS_EXECUTORS) |
b32b8144 FG |
226 | |
227 | /// The type used to count the number of handlers executed by the context. | |
228 | typedef std::size_t count_type; | |
229 | ||
230 | /// Constructor. | |
231 | BOOST_ASIO_DECL io_context(); | |
232 | ||
233 | /// Constructor. | |
234 | /** | |
235 | * Construct with a hint about the required level of concurrency. | |
236 | * | |
237 | * @param concurrency_hint A suggestion to the implementation on how many | |
238 | * threads it should allow to run simultaneously. | |
239 | */ | |
240 | BOOST_ASIO_DECL explicit io_context(int concurrency_hint); | |
241 | ||
242 | /// Destructor. | |
243 | /** | |
244 | * On destruction, the io_context performs the following sequence of | |
245 | * operations: | |
246 | * | |
247 | * @li For each service object @c svc in the io_context set, in reverse order | |
248 | * of the beginning of service object lifetime, performs | |
249 | * @c svc->shutdown(). | |
250 | * | |
251 | * @li Uninvoked handler objects that were scheduled for deferred invocation | |
252 | * on the io_context, or any associated strand, are destroyed. | |
253 | * | |
254 | * @li For each service object @c svc in the io_context set, in reverse order | |
255 | * of the beginning of service object lifetime, performs | |
256 | * <tt>delete static_cast<io_context::service*>(svc)</tt>. | |
257 | * | |
258 | * @note The destruction sequence described above permits programs to | |
259 | * simplify their resource management by using @c shared_ptr<>. Where an | |
260 | * object's lifetime is tied to the lifetime of a connection (or some other | |
261 | * sequence of asynchronous operations), a @c shared_ptr to the object would | |
262 | * be bound into the handlers for all asynchronous operations associated with | |
263 | * it. This works as follows: | |
264 | * | |
265 | * @li When a single connection ends, all associated asynchronous operations | |
266 | * complete. The corresponding handler objects are destroyed, and all | |
267 | * @c shared_ptr references to the objects are destroyed. | |
268 | * | |
269 | * @li To shut down the whole program, the io_context function stop() is | |
270 | * called to terminate any run() calls as soon as possible. The io_context | |
271 | * destructor defined above destroys all handlers, causing all @c shared_ptr | |
272 | * references to all connection objects to be destroyed. | |
273 | */ | |
274 | BOOST_ASIO_DECL ~io_context(); | |
275 | ||
276 | /// Obtains the executor associated with the io_context. | |
277 | executor_type get_executor() BOOST_ASIO_NOEXCEPT; | |
278 | ||
279 | /// Run the io_context object's event processing loop. | |
280 | /** | |
281 | * The run() function blocks until all work has finished and there are no | |
282 | * more handlers to be dispatched, or until the io_context has been stopped. | |
283 | * | |
284 | * Multiple threads may call the run() function to set up a pool of threads | |
285 | * from which the io_context may execute handlers. All threads that are | |
286 | * waiting in the pool are equivalent and the io_context may choose any one | |
287 | * of them to invoke a handler. | |
288 | * | |
289 | * A normal exit from the run() function implies that the io_context object | |
290 | * is stopped (the stopped() function returns @c true). Subsequent calls to | |
291 | * run(), run_one(), poll() or poll_one() will return immediately unless there | |
292 | * is a prior call to restart(). | |
293 | * | |
294 | * @return The number of handlers that were executed. | |
295 | * | |
296 | * @note Calling the run() function from a thread that is currently calling | |
297 | * one of run(), run_one(), run_for(), run_until(), poll() or poll_one() on | |
298 | * the same io_context object may introduce the potential for deadlock. It is | |
299 | * the caller's reponsibility to avoid this. | |
300 | * | |
301 | * The poll() function may also be used to dispatch ready handlers, but | |
302 | * without blocking. | |
303 | */ | |
304 | BOOST_ASIO_DECL count_type run(); | |
305 | ||
306 | #if !defined(BOOST_ASIO_NO_DEPRECATED) | |
307 | /// (Deprecated: Use non-error_code overload.) Run the io_context object's | |
308 | /// event processing loop. | |
309 | /** | |
310 | * The run() function blocks until all work has finished and there are no | |
311 | * more handlers to be dispatched, or until the io_context has been stopped. | |
312 | * | |
313 | * Multiple threads may call the run() function to set up a pool of threads | |
314 | * from which the io_context may execute handlers. All threads that are | |
315 | * waiting in the pool are equivalent and the io_context may choose any one | |
316 | * of them to invoke a handler. | |
317 | * | |
318 | * A normal exit from the run() function implies that the io_context object | |
319 | * is stopped (the stopped() function returns @c true). Subsequent calls to | |
320 | * run(), run_one(), poll() or poll_one() will return immediately unless there | |
321 | * is a prior call to restart(). | |
322 | * | |
323 | * @param ec Set to indicate what error occurred, if any. | |
324 | * | |
325 | * @return The number of handlers that were executed. | |
326 | * | |
327 | * @note Calling the run() function from a thread that is currently calling | |
328 | * one of run(), run_one(), run_for(), run_until(), poll() or poll_one() on | |
329 | * the same io_context object may introduce the potential for deadlock. It is | |
330 | * the caller's reponsibility to avoid this. | |
331 | * | |
332 | * The poll() function may also be used to dispatch ready handlers, but | |
333 | * without blocking. | |
334 | */ | |
335 | BOOST_ASIO_DECL count_type run(boost::system::error_code& ec); | |
336 | #endif // !defined(BOOST_ASIO_NO_DEPRECATED) | |
337 | ||
338 | #if defined(BOOST_ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION) | |
339 | /// Run the io_context object's event processing loop for a specified | |
340 | /// duration. | |
341 | /** | |
342 | * The run_for() function blocks until all work has finished and there are no | |
343 | * more handlers to be dispatched, until the io_context has been stopped, or | |
344 | * until the specified duration has elapsed. | |
345 | * | |
346 | * @param rel_time The duration for which the call may block. | |
347 | * | |
348 | * @return The number of handlers that were executed. | |
349 | */ | |
350 | template <typename Rep, typename Period> | |
351 | std::size_t run_for(const chrono::duration<Rep, Period>& rel_time); | |
352 | ||
353 | /// Run the io_context object's event processing loop until a specified time. | |
354 | /** | |
355 | * The run_until() function blocks until all work has finished and there are | |
356 | * no more handlers to be dispatched, until the io_context has been stopped, | |
357 | * or until the specified time has been reached. | |
358 | * | |
359 | * @param abs_time The time point until which the call may block. | |
360 | * | |
361 | * @return The number of handlers that were executed. | |
362 | */ | |
363 | template <typename Clock, typename Duration> | |
364 | std::size_t run_until(const chrono::time_point<Clock, Duration>& abs_time); | |
365 | #endif // defined(BOOST_ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION) | |
366 | ||
367 | /// Run the io_context object's event processing loop to execute at most one | |
368 | /// handler. | |
369 | /** | |
370 | * The run_one() function blocks until one handler has been dispatched, or | |
371 | * until the io_context has been stopped. | |
372 | * | |
373 | * @return The number of handlers that were executed. A zero return value | |
374 | * implies that the io_context object is stopped (the stopped() function | |
375 | * returns @c true). Subsequent calls to run(), run_one(), poll() or | |
376 | * poll_one() will return immediately unless there is a prior call to | |
377 | * restart(). | |
378 | * | |
379 | * @note Calling the run_one() function from a thread that is currently | |
380 | * calling one of run(), run_one(), run_for(), run_until(), poll() or | |
381 | * poll_one() on the same io_context object may introduce the potential for | |
382 | * deadlock. It is the caller's reponsibility to avoid this. | |
383 | */ | |
384 | BOOST_ASIO_DECL count_type run_one(); | |
385 | ||
386 | #if !defined(BOOST_ASIO_NO_DEPRECATED) | |
1e59de90 | 387 | /// (Deprecated: Use non-error_code overload.) Run the io_context object's |
b32b8144 FG |
388 | /// event processing loop to execute at most one handler. |
389 | /** | |
390 | * The run_one() function blocks until one handler has been dispatched, or | |
391 | * until the io_context has been stopped. | |
392 | * | |
393 | * @return The number of handlers that were executed. A zero return value | |
394 | * implies that the io_context object is stopped (the stopped() function | |
395 | * returns @c true). Subsequent calls to run(), run_one(), poll() or | |
396 | * poll_one() will return immediately unless there is a prior call to | |
397 | * restart(). | |
398 | * | |
399 | * @return The number of handlers that were executed. | |
400 | * | |
401 | * @note Calling the run_one() function from a thread that is currently | |
402 | * calling one of run(), run_one(), run_for(), run_until(), poll() or | |
403 | * poll_one() on the same io_context object may introduce the potential for | |
404 | * deadlock. It is the caller's reponsibility to avoid this. | |
405 | */ | |
406 | BOOST_ASIO_DECL count_type run_one(boost::system::error_code& ec); | |
407 | #endif // !defined(BOOST_ASIO_NO_DEPRECATED) | |
408 | ||
409 | #if defined(BOOST_ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION) | |
410 | /// Run the io_context object's event processing loop for a specified duration | |
411 | /// to execute at most one handler. | |
412 | /** | |
413 | * The run_one_for() function blocks until one handler has been dispatched, | |
414 | * until the io_context has been stopped, or until the specified duration has | |
415 | * elapsed. | |
416 | * | |
417 | * @param rel_time The duration for which the call may block. | |
418 | * | |
419 | * @return The number of handlers that were executed. | |
420 | */ | |
421 | template <typename Rep, typename Period> | |
422 | std::size_t run_one_for(const chrono::duration<Rep, Period>& rel_time); | |
423 | ||
424 | /// Run the io_context object's event processing loop until a specified time | |
425 | /// to execute at most one handler. | |
426 | /** | |
427 | * The run_one_until() function blocks until one handler has been dispatched, | |
428 | * until the io_context has been stopped, or until the specified time has | |
429 | * been reached. | |
430 | * | |
431 | * @param abs_time The time point until which the call may block. | |
432 | * | |
433 | * @return The number of handlers that were executed. | |
434 | */ | |
435 | template <typename Clock, typename Duration> | |
436 | std::size_t run_one_until( | |
437 | const chrono::time_point<Clock, Duration>& abs_time); | |
438 | #endif // defined(BOOST_ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION) | |
439 | ||
440 | /// Run the io_context object's event processing loop to execute ready | |
441 | /// handlers. | |
442 | /** | |
443 | * The poll() function runs handlers that are ready to run, without blocking, | |
444 | * until the io_context has been stopped or there are no more ready handlers. | |
445 | * | |
446 | * @return The number of handlers that were executed. | |
447 | */ | |
448 | BOOST_ASIO_DECL count_type poll(); | |
449 | ||
450 | #if !defined(BOOST_ASIO_NO_DEPRECATED) | |
451 | /// (Deprecated: Use non-error_code overload.) Run the io_context object's | |
452 | /// event processing loop to execute ready handlers. | |
453 | /** | |
454 | * The poll() function runs handlers that are ready to run, without blocking, | |
455 | * until the io_context has been stopped or there are no more ready handlers. | |
456 | * | |
457 | * @param ec Set to indicate what error occurred, if any. | |
458 | * | |
459 | * @return The number of handlers that were executed. | |
460 | */ | |
461 | BOOST_ASIO_DECL count_type poll(boost::system::error_code& ec); | |
462 | #endif // !defined(BOOST_ASIO_NO_DEPRECATED) | |
463 | ||
464 | /// Run the io_context object's event processing loop to execute one ready | |
465 | /// handler. | |
466 | /** | |
467 | * The poll_one() function runs at most one handler that is ready to run, | |
468 | * without blocking. | |
469 | * | |
470 | * @return The number of handlers that were executed. | |
471 | */ | |
472 | BOOST_ASIO_DECL count_type poll_one(); | |
473 | ||
474 | #if !defined(BOOST_ASIO_NO_DEPRECATED) | |
475 | /// (Deprecated: Use non-error_code overload.) Run the io_context object's | |
476 | /// event processing loop to execute one ready handler. | |
477 | /** | |
478 | * The poll_one() function runs at most one handler that is ready to run, | |
479 | * without blocking. | |
480 | * | |
481 | * @param ec Set to indicate what error occurred, if any. | |
482 | * | |
483 | * @return The number of handlers that were executed. | |
484 | */ | |
485 | BOOST_ASIO_DECL count_type poll_one(boost::system::error_code& ec); | |
486 | #endif // !defined(BOOST_ASIO_NO_DEPRECATED) | |
487 | ||
488 | /// Stop the io_context object's event processing loop. | |
489 | /** | |
490 | * This function does not block, but instead simply signals the io_context to | |
491 | * stop. All invocations of its run() or run_one() member functions should | |
492 | * return as soon as possible. Subsequent calls to run(), run_one(), poll() | |
493 | * or poll_one() will return immediately until restart() is called. | |
494 | */ | |
495 | BOOST_ASIO_DECL void stop(); | |
496 | ||
497 | /// Determine whether the io_context object has been stopped. | |
498 | /** | |
499 | * This function is used to determine whether an io_context object has been | |
500 | * stopped, either through an explicit call to stop(), or due to running out | |
501 | * of work. When an io_context object is stopped, calls to run(), run_one(), | |
502 | * poll() or poll_one() will return immediately without invoking any | |
503 | * handlers. | |
504 | * | |
505 | * @return @c true if the io_context object is stopped, otherwise @c false. | |
506 | */ | |
507 | BOOST_ASIO_DECL bool stopped() const; | |
508 | ||
509 | /// Restart the io_context in preparation for a subsequent run() invocation. | |
510 | /** | |
511 | * This function must be called prior to any second or later set of | |
512 | * invocations of the run(), run_one(), poll() or poll_one() functions when a | |
513 | * previous invocation of these functions returned due to the io_context | |
514 | * being stopped or running out of work. After a call to restart(), the | |
515 | * io_context object's stopped() function will return @c false. | |
516 | * | |
517 | * This function must not be called while there are any unfinished calls to | |
518 | * the run(), run_one(), poll() or poll_one() functions. | |
519 | */ | |
520 | BOOST_ASIO_DECL void restart(); | |
521 | ||
522 | #if !defined(BOOST_ASIO_NO_DEPRECATED) | |
523 | /// (Deprecated: Use restart().) Reset the io_context in preparation for a | |
524 | /// subsequent run() invocation. | |
525 | /** | |
526 | * This function must be called prior to any second or later set of | |
527 | * invocations of the run(), run_one(), poll() or poll_one() functions when a | |
528 | * previous invocation of these functions returned due to the io_context | |
529 | * being stopped or running out of work. After a call to restart(), the | |
530 | * io_context object's stopped() function will return @c false. | |
531 | * | |
532 | * This function must not be called while there are any unfinished calls to | |
533 | * the run(), run_one(), poll() or poll_one() functions. | |
534 | */ | |
535 | void reset(); | |
536 | ||
537 | /// (Deprecated: Use boost::asio::dispatch().) Request the io_context to | |
538 | /// invoke the given handler. | |
539 | /** | |
540 | * This function is used to ask the io_context to execute the given handler. | |
541 | * | |
542 | * The io_context guarantees that the handler will only be called in a thread | |
543 | * in which the run(), run_one(), poll() or poll_one() member functions is | |
544 | * currently being invoked. The handler may be executed inside this function | |
545 | * if the guarantee can be met. | |
546 | * | |
547 | * @param handler The handler to be called. The io_context will make | |
548 | * a copy of the handler object as required. The function signature of the | |
549 | * handler must be: @code void handler(); @endcode | |
550 | * | |
551 | * @note This function throws an exception only if: | |
552 | * | |
553 | * @li the handler's @c asio_handler_allocate function; or | |
554 | * | |
555 | * @li the handler's copy constructor | |
556 | * | |
557 | * throws an exception. | |
558 | */ | |
11fdf7f2 | 559 | template <typename LegacyCompletionHandler> |
92f5a8d4 | 560 | BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ()) |
11fdf7f2 | 561 | dispatch(BOOST_ASIO_MOVE_ARG(LegacyCompletionHandler) handler); |
b32b8144 FG |
562 | |
563 | /// (Deprecated: Use boost::asio::post().) Request the io_context to invoke | |
564 | /// the given handler and return immediately. | |
565 | /** | |
566 | * This function is used to ask the io_context to execute the given handler, | |
567 | * but without allowing the io_context to call the handler from inside this | |
568 | * function. | |
569 | * | |
570 | * The io_context guarantees that the handler will only be called in a thread | |
571 | * in which the run(), run_one(), poll() or poll_one() member functions is | |
572 | * currently being invoked. | |
573 | * | |
574 | * @param handler The handler to be called. The io_context will make | |
575 | * a copy of the handler object as required. The function signature of the | |
576 | * handler must be: @code void handler(); @endcode | |
577 | * | |
578 | * @note This function throws an exception only if: | |
579 | * | |
580 | * @li the handler's @c asio_handler_allocate function; or | |
581 | * | |
582 | * @li the handler's copy constructor | |
583 | * | |
584 | * throws an exception. | |
585 | */ | |
11fdf7f2 | 586 | template <typename LegacyCompletionHandler> |
92f5a8d4 | 587 | BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ()) |
11fdf7f2 | 588 | post(BOOST_ASIO_MOVE_ARG(LegacyCompletionHandler) handler); |
b32b8144 FG |
589 | |
590 | /// (Deprecated: Use boost::asio::bind_executor().) Create a new handler that | |
591 | /// automatically dispatches the wrapped handler on the io_context. | |
592 | /** | |
593 | * This function is used to create a new handler function object that, when | |
594 | * invoked, will automatically pass the wrapped handler to the io_context | |
595 | * object's dispatch function. | |
596 | * | |
597 | * @param handler The handler to be wrapped. The io_context will make a copy | |
598 | * of the handler object as required. The function signature of the handler | |
599 | * must be: @code void handler(A1 a1, ... An an); @endcode | |
600 | * | |
601 | * @return A function object that, when invoked, passes the wrapped handler to | |
602 | * the io_context object's dispatch function. Given a function object with the | |
603 | * signature: | |
604 | * @code R f(A1 a1, ... An an); @endcode | |
605 | * If this function object is passed to the wrap function like so: | |
606 | * @code io_context.wrap(f); @endcode | |
607 | * then the return value is a function object with the signature | |
608 | * @code void g(A1 a1, ... An an); @endcode | |
609 | * that, when invoked, executes code equivalent to: | |
610 | * @code io_context.dispatch(boost::bind(f, a1, ... an)); @endcode | |
611 | */ | |
612 | template <typename Handler> | |
613 | #if defined(GENERATING_DOCUMENTATION) | |
614 | unspecified | |
615 | #else | |
616 | detail::wrapped_handler<io_context&, Handler> | |
617 | #endif | |
618 | wrap(Handler handler); | |
619 | #endif // !defined(BOOST_ASIO_NO_DEPRECATED) | |
620 | ||
621 | private: | |
20effc67 TL |
622 | io_context(const io_context&) BOOST_ASIO_DELETED; |
623 | io_context& operator=(const io_context&) BOOST_ASIO_DELETED; | |
624 | ||
92f5a8d4 TL |
625 | #if !defined(BOOST_ASIO_NO_DEPRECATED) |
626 | struct initiate_dispatch; | |
627 | struct initiate_post; | |
628 | #endif // !defined(BOOST_ASIO_NO_DEPRECATED) | |
629 | ||
b32b8144 FG |
630 | // Helper function to add the implementation. |
631 | BOOST_ASIO_DECL impl_type& add_impl(impl_type* impl); | |
632 | ||
633 | // Backwards compatible overload for use with services derived from | |
634 | // io_context::service. | |
635 | template <typename Service> | |
636 | friend Service& use_service(io_context& ioc); | |
637 | ||
638 | #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) | |
639 | detail::winsock_init<> init_; | |
640 | #elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \ | |
641 | || defined(__osf__) | |
642 | detail::signal_init<> init_; | |
643 | #endif | |
644 | ||
645 | // The implementation. | |
646 | impl_type& impl_; | |
647 | }; | |
648 | ||
20effc67 TL |
649 | namespace detail { |
650 | ||
651 | } // namespace detail | |
652 | ||
653 | /// Executor implementation type used to submit functions to an io_context. | |
1e59de90 TL |
654 | template <typename Allocator, uintptr_t Bits> |
655 | class io_context::basic_executor_type : | |
656 | detail::io_context_bits, Allocator | |
b32b8144 FG |
657 | { |
658 | public: | |
20effc67 TL |
659 | /// Copy constructor. |
660 | basic_executor_type( | |
661 | const basic_executor_type& other) BOOST_ASIO_NOEXCEPT | |
1e59de90 TL |
662 | : Allocator(static_cast<const Allocator&>(other)), |
663 | target_(other.target_) | |
20effc67 TL |
664 | { |
665 | if (Bits & outstanding_work_tracked) | |
1e59de90 TL |
666 | if (context_ptr()) |
667 | context_ptr()->impl_.work_started(); | |
20effc67 TL |
668 | } |
669 | ||
670 | #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) | |
671 | /// Move constructor. | |
672 | basic_executor_type(basic_executor_type&& other) BOOST_ASIO_NOEXCEPT | |
1e59de90 TL |
673 | : Allocator(BOOST_ASIO_MOVE_CAST(Allocator)(other)), |
674 | target_(other.target_) | |
20effc67 TL |
675 | { |
676 | if (Bits & outstanding_work_tracked) | |
1e59de90 | 677 | other.target_ = 0; |
20effc67 TL |
678 | } |
679 | #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) | |
680 | ||
681 | /// Destructor. | |
682 | ~basic_executor_type() BOOST_ASIO_NOEXCEPT | |
683 | { | |
684 | if (Bits & outstanding_work_tracked) | |
1e59de90 TL |
685 | if (context_ptr()) |
686 | context_ptr()->impl_.work_finished(); | |
20effc67 TL |
687 | } |
688 | ||
689 | /// Assignment operator. | |
690 | basic_executor_type& operator=( | |
691 | const basic_executor_type& other) BOOST_ASIO_NOEXCEPT; | |
692 | ||
693 | #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) | |
694 | /// Move assignment operator. | |
695 | basic_executor_type& operator=( | |
696 | basic_executor_type&& other) BOOST_ASIO_NOEXCEPT; | |
697 | #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) | |
698 | ||
1e59de90 TL |
699 | #if !defined(GENERATING_DOCUMENTATION) |
700 | private: | |
701 | friend struct boost_asio_require_fn::impl; | |
702 | friend struct boost_asio_prefer_fn::impl; | |
703 | #endif // !defined(GENERATING_DOCUMENTATION) | |
704 | ||
20effc67 TL |
705 | /// Obtain an executor with the @c blocking.possibly property. |
706 | /** | |
707 | * Do not call this function directly. It is intended for use with the | |
708 | * boost::asio::require customisation point. | |
709 | * | |
710 | * For example: | |
711 | * @code auto ex1 = my_io_context.get_executor(); | |
712 | * auto ex2 = boost::asio::require(ex1, | |
713 | * boost::asio::execution::blocking.possibly); @endcode | |
714 | */ | |
715 | BOOST_ASIO_CONSTEXPR basic_executor_type require( | |
716 | execution::blocking_t::possibly_t) const | |
717 | { | |
1e59de90 TL |
718 | return basic_executor_type(context_ptr(), |
719 | *this, bits() & ~blocking_never); | |
20effc67 TL |
720 | } |
721 | ||
722 | /// Obtain an executor with the @c blocking.never property. | |
723 | /** | |
724 | * Do not call this function directly. It is intended for use with the | |
725 | * boost::asio::require customisation point. | |
726 | * | |
727 | * For example: | |
728 | * @code auto ex1 = my_io_context.get_executor(); | |
729 | * auto ex2 = boost::asio::require(ex1, | |
730 | * boost::asio::execution::blocking.never); @endcode | |
731 | */ | |
732 | BOOST_ASIO_CONSTEXPR basic_executor_type require( | |
733 | execution::blocking_t::never_t) const | |
734 | { | |
1e59de90 TL |
735 | return basic_executor_type(context_ptr(), |
736 | *this, bits() | blocking_never); | |
20effc67 TL |
737 | } |
738 | ||
739 | /// Obtain an executor with the @c relationship.fork property. | |
740 | /** | |
741 | * Do not call this function directly. It is intended for use with the | |
742 | * boost::asio::require customisation point. | |
743 | * | |
744 | * For example: | |
745 | * @code auto ex1 = my_io_context.get_executor(); | |
746 | * auto ex2 = boost::asio::require(ex1, | |
747 | * boost::asio::execution::relationship.fork); @endcode | |
748 | */ | |
749 | BOOST_ASIO_CONSTEXPR basic_executor_type require( | |
750 | execution::relationship_t::fork_t) const | |
751 | { | |
1e59de90 TL |
752 | return basic_executor_type(context_ptr(), |
753 | *this, bits() & ~relationship_continuation); | |
20effc67 TL |
754 | } |
755 | ||
756 | /// Obtain an executor with the @c relationship.continuation property. | |
757 | /** | |
758 | * Do not call this function directly. It is intended for use with the | |
759 | * boost::asio::require customisation point. | |
760 | * | |
761 | * For example: | |
762 | * @code auto ex1 = my_io_context.get_executor(); | |
763 | * auto ex2 = boost::asio::require(ex1, | |
764 | * boost::asio::execution::relationship.continuation); @endcode | |
765 | */ | |
766 | BOOST_ASIO_CONSTEXPR basic_executor_type require( | |
767 | execution::relationship_t::continuation_t) const | |
768 | { | |
1e59de90 TL |
769 | return basic_executor_type(context_ptr(), |
770 | *this, bits() | relationship_continuation); | |
20effc67 TL |
771 | } |
772 | ||
773 | /// Obtain an executor with the @c outstanding_work.tracked property. | |
774 | /** | |
775 | * Do not call this function directly. It is intended for use with the | |
776 | * boost::asio::require customisation point. | |
777 | * | |
778 | * For example: | |
779 | * @code auto ex1 = my_io_context.get_executor(); | |
780 | * auto ex2 = boost::asio::require(ex1, | |
781 | * boost::asio::execution::outstanding_work.tracked); @endcode | |
782 | */ | |
783 | BOOST_ASIO_CONSTEXPR basic_executor_type<Allocator, | |
784 | BOOST_ASIO_UNSPECIFIED(Bits | outstanding_work_tracked)> | |
785 | require(execution::outstanding_work_t::tracked_t) const | |
786 | { | |
787 | return basic_executor_type<Allocator, Bits | outstanding_work_tracked>( | |
1e59de90 | 788 | context_ptr(), *this, bits()); |
20effc67 TL |
789 | } |
790 | ||
791 | /// Obtain an executor with the @c outstanding_work.untracked property. | |
792 | /** | |
793 | * Do not call this function directly. It is intended for use with the | |
794 | * boost::asio::require customisation point. | |
795 | * | |
796 | * For example: | |
797 | * @code auto ex1 = my_io_context.get_executor(); | |
798 | * auto ex2 = boost::asio::require(ex1, | |
799 | * boost::asio::execution::outstanding_work.untracked); @endcode | |
800 | */ | |
801 | BOOST_ASIO_CONSTEXPR basic_executor_type<Allocator, | |
802 | BOOST_ASIO_UNSPECIFIED(Bits & ~outstanding_work_tracked)> | |
803 | require(execution::outstanding_work_t::untracked_t) const | |
804 | { | |
805 | return basic_executor_type<Allocator, Bits & ~outstanding_work_tracked>( | |
1e59de90 | 806 | context_ptr(), *this, bits()); |
20effc67 TL |
807 | } |
808 | ||
809 | /// Obtain an executor with the specified @c allocator property. | |
810 | /** | |
811 | * Do not call this function directly. It is intended for use with the | |
812 | * boost::asio::require customisation point. | |
813 | * | |
814 | * For example: | |
815 | * @code auto ex1 = my_io_context.get_executor(); | |
816 | * auto ex2 = boost::asio::require(ex1, | |
817 | * boost::asio::execution::allocator(my_allocator)); @endcode | |
818 | */ | |
819 | template <typename OtherAllocator> | |
820 | BOOST_ASIO_CONSTEXPR basic_executor_type<OtherAllocator, Bits> | |
821 | require(execution::allocator_t<OtherAllocator> a) const | |
822 | { | |
823 | return basic_executor_type<OtherAllocator, Bits>( | |
1e59de90 | 824 | context_ptr(), a.value(), bits()); |
20effc67 TL |
825 | } |
826 | ||
827 | /// Obtain an executor with the default @c allocator property. | |
828 | /** | |
829 | * Do not call this function directly. It is intended for use with the | |
830 | * boost::asio::require customisation point. | |
831 | * | |
832 | * For example: | |
833 | * @code auto ex1 = my_io_context.get_executor(); | |
834 | * auto ex2 = boost::asio::require(ex1, | |
835 | * boost::asio::execution::allocator); @endcode | |
836 | */ | |
837 | BOOST_ASIO_CONSTEXPR basic_executor_type<std::allocator<void>, Bits> | |
838 | require(execution::allocator_t<void>) const | |
839 | { | |
840 | return basic_executor_type<std::allocator<void>, Bits>( | |
1e59de90 | 841 | context_ptr(), std::allocator<void>(), bits()); |
20effc67 TL |
842 | } |
843 | ||
1e59de90 TL |
844 | #if !defined(GENERATING_DOCUMENTATION) |
845 | private: | |
846 | friend struct boost_asio_query_fn::impl; | |
847 | friend struct boost::asio::execution::detail::mapping_t<0>; | |
848 | friend struct boost::asio::execution::detail::outstanding_work_t<0>; | |
849 | #endif // !defined(GENERATING_DOCUMENTATION) | |
850 | ||
20effc67 TL |
851 | /// Query the current value of the @c mapping property. |
852 | /** | |
853 | * Do not call this function directly. It is intended for use with the | |
854 | * boost::asio::query customisation point. | |
855 | * | |
856 | * For example: | |
857 | * @code auto ex = my_io_context.get_executor(); | |
858 | * if (boost::asio::query(ex, boost::asio::execution::mapping) | |
859 | * == boost::asio::execution::mapping.thread) | |
860 | * ... @endcode | |
861 | */ | |
862 | static BOOST_ASIO_CONSTEXPR execution::mapping_t query( | |
863 | execution::mapping_t) BOOST_ASIO_NOEXCEPT | |
864 | { | |
865 | return execution::mapping.thread; | |
866 | } | |
867 | ||
868 | /// Query the current value of the @c context property. | |
869 | /** | |
870 | * Do not call this function directly. It is intended for use with the | |
871 | * boost::asio::query customisation point. | |
872 | * | |
873 | * For example: | |
874 | * @code auto ex = my_io_context.get_executor(); | |
875 | * boost::asio::io_context& ctx = boost::asio::query( | |
876 | * ex, boost::asio::execution::context); @endcode | |
877 | */ | |
878 | io_context& query(execution::context_t) const BOOST_ASIO_NOEXCEPT | |
879 | { | |
1e59de90 | 880 | return *context_ptr(); |
20effc67 TL |
881 | } |
882 | ||
883 | /// Query the current value of the @c blocking property. | |
884 | /** | |
885 | * Do not call this function directly. It is intended for use with the | |
886 | * boost::asio::query customisation point. | |
887 | * | |
888 | * For example: | |
889 | * @code auto ex = my_io_context.get_executor(); | |
890 | * if (boost::asio::query(ex, boost::asio::execution::blocking) | |
891 | * == boost::asio::execution::blocking.always) | |
892 | * ... @endcode | |
893 | */ | |
894 | BOOST_ASIO_CONSTEXPR execution::blocking_t query( | |
895 | execution::blocking_t) const BOOST_ASIO_NOEXCEPT | |
896 | { | |
1e59de90 | 897 | return (bits() & blocking_never) |
20effc67 TL |
898 | ? execution::blocking_t(execution::blocking.never) |
899 | : execution::blocking_t(execution::blocking.possibly); | |
900 | } | |
901 | ||
902 | /// Query the current value of the @c relationship property. | |
903 | /** | |
904 | * Do not call this function directly. It is intended for use with the | |
905 | * boost::asio::query customisation point. | |
906 | * | |
907 | * For example: | |
908 | * @code auto ex = my_io_context.get_executor(); | |
909 | * if (boost::asio::query(ex, boost::asio::execution::relationship) | |
910 | * == boost::asio::execution::relationship.continuation) | |
911 | * ... @endcode | |
912 | */ | |
913 | BOOST_ASIO_CONSTEXPR execution::relationship_t query( | |
914 | execution::relationship_t) const BOOST_ASIO_NOEXCEPT | |
915 | { | |
1e59de90 | 916 | return (bits() & relationship_continuation) |
20effc67 TL |
917 | ? execution::relationship_t(execution::relationship.continuation) |
918 | : execution::relationship_t(execution::relationship.fork); | |
919 | } | |
920 | ||
921 | /// Query the current value of the @c outstanding_work property. | |
922 | /** | |
923 | * Do not call this function directly. It is intended for use with the | |
924 | * boost::asio::query customisation point. | |
925 | * | |
926 | * For example: | |
927 | * @code auto ex = my_io_context.get_executor(); | |
928 | * if (boost::asio::query(ex, boost::asio::execution::outstanding_work) | |
929 | * == boost::asio::execution::outstanding_work.tracked) | |
930 | * ... @endcode | |
931 | */ | |
932 | static BOOST_ASIO_CONSTEXPR execution::outstanding_work_t query( | |
933 | execution::outstanding_work_t) BOOST_ASIO_NOEXCEPT | |
934 | { | |
935 | return (Bits & outstanding_work_tracked) | |
936 | ? execution::outstanding_work_t(execution::outstanding_work.tracked) | |
937 | : execution::outstanding_work_t(execution::outstanding_work.untracked); | |
938 | } | |
939 | ||
940 | /// Query the current value of the @c allocator property. | |
941 | /** | |
942 | * Do not call this function directly. It is intended for use with the | |
943 | * boost::asio::query customisation point. | |
944 | * | |
945 | * For example: | |
946 | * @code auto ex = my_io_context.get_executor(); | |
947 | * auto alloc = boost::asio::query(ex, | |
948 | * boost::asio::execution::allocator); @endcode | |
949 | */ | |
950 | template <typename OtherAllocator> | |
951 | BOOST_ASIO_CONSTEXPR Allocator query( | |
952 | execution::allocator_t<OtherAllocator>) const BOOST_ASIO_NOEXCEPT | |
953 | { | |
1e59de90 | 954 | return static_cast<const Allocator&>(*this); |
20effc67 TL |
955 | } |
956 | ||
957 | /// Query the current value of the @c allocator property. | |
958 | /** | |
959 | * Do not call this function directly. It is intended for use with the | |
960 | * boost::asio::query customisation point. | |
961 | * | |
962 | * For example: | |
963 | * @code auto ex = my_io_context.get_executor(); | |
964 | * auto alloc = boost::asio::query(ex, | |
965 | * boost::asio::execution::allocator); @endcode | |
966 | */ | |
967 | BOOST_ASIO_CONSTEXPR Allocator query( | |
968 | execution::allocator_t<void>) const BOOST_ASIO_NOEXCEPT | |
969 | { | |
1e59de90 | 970 | return static_cast<const Allocator&>(*this); |
20effc67 TL |
971 | } |
972 | ||
1e59de90 | 973 | public: |
20effc67 TL |
974 | /// Determine whether the io_context is running in the current thread. |
975 | /** | |
976 | * @return @c true if the current thread is running the io_context. Otherwise | |
977 | * returns @c false. | |
978 | */ | |
979 | bool running_in_this_thread() const BOOST_ASIO_NOEXCEPT; | |
980 | ||
981 | /// Compare two executors for equality. | |
982 | /** | |
983 | * Two executors are equal if they refer to the same underlying io_context. | |
984 | */ | |
985 | friend bool operator==(const basic_executor_type& a, | |
986 | const basic_executor_type& b) BOOST_ASIO_NOEXCEPT | |
987 | { | |
1e59de90 TL |
988 | return a.target_ == b.target_ |
989 | && static_cast<const Allocator&>(a) == static_cast<const Allocator&>(b); | |
20effc67 TL |
990 | } |
991 | ||
992 | /// Compare two executors for inequality. | |
993 | /** | |
994 | * Two executors are equal if they refer to the same underlying io_context. | |
995 | */ | |
996 | friend bool operator!=(const basic_executor_type& a, | |
997 | const basic_executor_type& b) BOOST_ASIO_NOEXCEPT | |
998 | { | |
1e59de90 TL |
999 | return a.target_ != b.target_ |
1000 | || static_cast<const Allocator&>(a) != static_cast<const Allocator&>(b); | |
20effc67 TL |
1001 | } |
1002 | ||
1e59de90 TL |
1003 | #if !defined(GENERATING_DOCUMENTATION) |
1004 | private: | |
1005 | friend struct boost_asio_execution_execute_fn::impl; | |
1006 | #endif // !defined(GENERATING_DOCUMENTATION) | |
1007 | ||
20effc67 TL |
1008 | /// Execution function. |
1009 | /** | |
1010 | * Do not call this function directly. It is intended for use with the | |
1011 | * execution::execute customisation point. | |
1012 | * | |
1013 | * For example: | |
1014 | * @code auto ex = my_io_context.get_executor(); | |
1015 | * execution::execute(ex, my_function_object); @endcode | |
1016 | */ | |
1017 | template <typename Function> | |
1018 | void execute(BOOST_ASIO_MOVE_ARG(Function) f) const; | |
1019 | ||
1020 | #if !defined(BOOST_ASIO_NO_TS_EXECUTORS) | |
1e59de90 | 1021 | public: |
b32b8144 FG |
1022 | /// Obtain the underlying execution context. |
1023 | io_context& context() const BOOST_ASIO_NOEXCEPT; | |
1024 | ||
1025 | /// Inform the io_context that it has some outstanding work to do. | |
1026 | /** | |
1027 | * This function is used to inform the io_context that some work has begun. | |
1028 | * This ensures that the io_context's run() and run_one() functions do not | |
1029 | * exit while the work is underway. | |
1030 | */ | |
1031 | void on_work_started() const BOOST_ASIO_NOEXCEPT; | |
1032 | ||
1033 | /// Inform the io_context that some work is no longer outstanding. | |
1034 | /** | |
1035 | * This function is used to inform the io_context that some work has | |
1036 | * finished. Once the count of unfinished work reaches zero, the io_context | |
1037 | * is stopped and the run() and run_one() functions may exit. | |
1038 | */ | |
1039 | void on_work_finished() const BOOST_ASIO_NOEXCEPT; | |
1040 | ||
1041 | /// Request the io_context to invoke the given function object. | |
1042 | /** | |
1043 | * This function is used to ask the io_context to execute the given function | |
1044 | * object. If the current thread is running the io_context, @c dispatch() | |
1045 | * executes the function before returning. Otherwise, the function will be | |
1046 | * scheduled to run on the io_context. | |
1047 | * | |
1048 | * @param f The function object to be called. The executor will make a copy | |
1049 | * of the handler object as required. The function signature of the function | |
1050 | * object must be: @code void function(); @endcode | |
1051 | * | |
1052 | * @param a An allocator that may be used by the executor to allocate the | |
1053 | * internal storage needed for function invocation. | |
1054 | */ | |
20effc67 TL |
1055 | template <typename Function, typename OtherAllocator> |
1056 | void dispatch(BOOST_ASIO_MOVE_ARG(Function) f, | |
1057 | const OtherAllocator& a) const; | |
b32b8144 FG |
1058 | |
1059 | /// Request the io_context to invoke the given function object. | |
1060 | /** | |
1061 | * This function is used to ask the io_context to execute the given function | |
1062 | * object. The function object will never be executed inside @c post(). | |
1063 | * Instead, it will be scheduled to run on the io_context. | |
1064 | * | |
1065 | * @param f The function object to be called. The executor will make a copy | |
1066 | * of the handler object as required. The function signature of the function | |
1067 | * object must be: @code void function(); @endcode | |
1068 | * | |
1069 | * @param a An allocator that may be used by the executor to allocate the | |
1070 | * internal storage needed for function invocation. | |
1071 | */ | |
20effc67 TL |
1072 | template <typename Function, typename OtherAllocator> |
1073 | void post(BOOST_ASIO_MOVE_ARG(Function) f, | |
1074 | const OtherAllocator& a) const; | |
b32b8144 FG |
1075 | |
1076 | /// Request the io_context to invoke the given function object. | |
1077 | /** | |
1078 | * This function is used to ask the io_context to execute the given function | |
1079 | * object. The function object will never be executed inside @c defer(). | |
1080 | * Instead, it will be scheduled to run on the io_context. | |
1081 | * | |
1082 | * If the current thread belongs to the io_context, @c defer() will delay | |
1083 | * scheduling the function object until the current thread returns control to | |
1084 | * the pool. | |
1085 | * | |
1086 | * @param f The function object to be called. The executor will make a copy | |
1087 | * of the handler object as required. The function signature of the function | |
1088 | * object must be: @code void function(); @endcode | |
1089 | * | |
1090 | * @param a An allocator that may be used by the executor to allocate the | |
1091 | * internal storage needed for function invocation. | |
1092 | */ | |
20effc67 TL |
1093 | template <typename Function, typename OtherAllocator> |
1094 | void defer(BOOST_ASIO_MOVE_ARG(Function) f, | |
1095 | const OtherAllocator& a) const; | |
1096 | #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS) | |
b32b8144 | 1097 | |
20effc67 TL |
1098 | private: |
1099 | friend class io_context; | |
1e59de90 | 1100 | template <typename, uintptr_t> friend class basic_executor_type; |
b32b8144 | 1101 | |
20effc67 TL |
1102 | // Constructor used by io_context::get_executor(). |
1103 | explicit basic_executor_type(io_context& i) BOOST_ASIO_NOEXCEPT | |
1e59de90 TL |
1104 | : Allocator(), |
1105 | target_(reinterpret_cast<uintptr_t>(&i)) | |
b32b8144 | 1106 | { |
20effc67 | 1107 | if (Bits & outstanding_work_tracked) |
1e59de90 | 1108 | context_ptr()->impl_.work_started(); |
b32b8144 FG |
1109 | } |
1110 | ||
20effc67 TL |
1111 | // Constructor used by require(). |
1112 | basic_executor_type(io_context* i, | |
1e59de90 TL |
1113 | const Allocator& a, uintptr_t bits) BOOST_ASIO_NOEXCEPT |
1114 | : Allocator(a), | |
1115 | target_(reinterpret_cast<uintptr_t>(i) | bits) | |
b32b8144 | 1116 | { |
20effc67 | 1117 | if (Bits & outstanding_work_tracked) |
1e59de90 TL |
1118 | if (context_ptr()) |
1119 | context_ptr()->impl_.work_started(); | |
b32b8144 FG |
1120 | } |
1121 | ||
1e59de90 TL |
1122 | io_context* context_ptr() const BOOST_ASIO_NOEXCEPT |
1123 | { | |
1124 | return reinterpret_cast<io_context*>(target_ & ~runtime_bits); | |
1125 | } | |
b32b8144 | 1126 | |
1e59de90 TL |
1127 | uintptr_t bits() const BOOST_ASIO_NOEXCEPT |
1128 | { | |
1129 | return target_ & runtime_bits; | |
1130 | } | |
b32b8144 | 1131 | |
1e59de90 TL |
1132 | // The underlying io_context and runtime bits. |
1133 | uintptr_t target_; | |
b32b8144 FG |
1134 | }; |
1135 | ||
1136 | #if !defined(BOOST_ASIO_NO_DEPRECATED) | |
1137 | /// (Deprecated: Use executor_work_guard.) Class to inform the io_context when | |
1138 | /// it has work to do. | |
1139 | /** | |
1140 | * The work class is used to inform the io_context when work starts and | |
1141 | * finishes. This ensures that the io_context object's run() function will not | |
1142 | * exit while work is underway, and that it does exit when there is no | |
1143 | * unfinished work remaining. | |
1144 | * | |
1145 | * The work class is copy-constructible so that it may be used as a data member | |
1146 | * in a handler class. It is not assignable. | |
1147 | */ | |
1148 | class io_context::work | |
1149 | { | |
1150 | public: | |
1151 | /// Constructor notifies the io_context that work is starting. | |
1152 | /** | |
1153 | * The constructor is used to inform the io_context that some work has begun. | |
1154 | * This ensures that the io_context object's run() function will not exit | |
1155 | * while the work is underway. | |
1156 | */ | |
1157 | explicit work(boost::asio::io_context& io_context); | |
1158 | ||
1159 | /// Copy constructor notifies the io_context that work is starting. | |
1160 | /** | |
1161 | * The constructor is used to inform the io_context that some work has begun. | |
1162 | * This ensures that the io_context object's run() function will not exit | |
1163 | * while the work is underway. | |
1164 | */ | |
1165 | work(const work& other); | |
1166 | ||
1167 | /// Destructor notifies the io_context that the work is complete. | |
1168 | /** | |
1169 | * The destructor is used to inform the io_context that some work has | |
1170 | * finished. Once the count of unfinished work reaches zero, the io_context | |
1171 | * object's run() function is permitted to exit. | |
1172 | */ | |
1173 | ~work(); | |
1174 | ||
1175 | /// Get the io_context associated with the work. | |
1176 | boost::asio::io_context& get_io_context(); | |
1177 | ||
b32b8144 FG |
1178 | private: |
1179 | // Prevent assignment. | |
1180 | void operator=(const work& other); | |
1181 | ||
1182 | // The io_context implementation. | |
1183 | detail::io_context_impl& io_context_impl_; | |
1184 | }; | |
1185 | #endif // !defined(BOOST_ASIO_NO_DEPRECATED) | |
1186 | ||
1187 | /// Base class for all io_context services. | |
1188 | class io_context::service | |
1189 | : public execution_context::service | |
1190 | { | |
1191 | public: | |
1192 | /// Get the io_context object that owns the service. | |
1193 | boost::asio::io_context& get_io_context(); | |
1194 | ||
b32b8144 FG |
1195 | private: |
1196 | /// Destroy all user-defined handler objects owned by the service. | |
1197 | BOOST_ASIO_DECL virtual void shutdown(); | |
1198 | ||
1199 | #if !defined(BOOST_ASIO_NO_DEPRECATED) | |
1200 | /// (Deprecated: Use shutdown().) Destroy all user-defined handler objects | |
1201 | /// owned by the service. | |
1202 | BOOST_ASIO_DECL virtual void shutdown_service(); | |
1203 | #endif // !defined(BOOST_ASIO_NO_DEPRECATED) | |
1204 | ||
1205 | /// Handle notification of a fork-related event to perform any necessary | |
1206 | /// housekeeping. | |
1207 | /** | |
1208 | * This function is not a pure virtual so that services only have to | |
1209 | * implement it if necessary. The default implementation does nothing. | |
1210 | */ | |
1211 | BOOST_ASIO_DECL virtual void notify_fork( | |
1212 | execution_context::fork_event event); | |
1213 | ||
1214 | #if !defined(BOOST_ASIO_NO_DEPRECATED) | |
1215 | /// (Deprecated: Use notify_fork().) Handle notification of a fork-related | |
1216 | /// event to perform any necessary housekeeping. | |
1217 | /** | |
1218 | * This function is not a pure virtual so that services only have to | |
1219 | * implement it if necessary. The default implementation does nothing. | |
1220 | */ | |
1221 | BOOST_ASIO_DECL virtual void fork_service( | |
1222 | execution_context::fork_event event); | |
1223 | #endif // !defined(BOOST_ASIO_NO_DEPRECATED) | |
1224 | ||
1225 | protected: | |
1226 | /// Constructor. | |
1227 | /** | |
1228 | * @param owner The io_context object that owns the service. | |
1229 | */ | |
1230 | BOOST_ASIO_DECL service(boost::asio::io_context& owner); | |
1231 | ||
1232 | /// Destructor. | |
1233 | BOOST_ASIO_DECL virtual ~service(); | |
1234 | }; | |
1235 | ||
1236 | namespace detail { | |
1237 | ||
1238 | // Special service base class to keep classes header-file only. | |
1239 | template <typename Type> | |
1240 | class service_base | |
1241 | : public boost::asio::io_context::service | |
1242 | { | |
1243 | public: | |
1244 | static boost::asio::detail::service_id<Type> id; | |
1245 | ||
1246 | // Constructor. | |
1247 | service_base(boost::asio::io_context& io_context) | |
1248 | : boost::asio::io_context::service(io_context) | |
1249 | { | |
1250 | } | |
1251 | }; | |
1252 | ||
1253 | template <typename Type> | |
1254 | boost::asio::detail::service_id<Type> service_base<Type>::id; | |
1255 | ||
1256 | } // namespace detail | |
20effc67 TL |
1257 | |
1258 | #if !defined(GENERATING_DOCUMENTATION) | |
1259 | ||
1260 | namespace traits { | |
1261 | ||
1262 | #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) | |
1263 | ||
1e59de90 | 1264 | template <typename Allocator, uintptr_t Bits> |
20effc67 TL |
1265 | struct equality_comparable< |
1266 | boost::asio::io_context::basic_executor_type<Allocator, Bits> | |
1267 | > | |
1268 | { | |
1269 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1270 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
1271 | }; | |
1272 | ||
1273 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) | |
1274 | ||
1275 | #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) | |
1276 | ||
1e59de90 | 1277 | template <typename Allocator, uintptr_t Bits, typename Function> |
20effc67 TL |
1278 | struct execute_member< |
1279 | boost::asio::io_context::basic_executor_type<Allocator, Bits>, | |
1280 | Function | |
1281 | > | |
1282 | { | |
1283 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1284 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | |
1285 | typedef void result_type; | |
1286 | }; | |
1287 | ||
1288 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) | |
1289 | ||
1290 | #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) | |
1291 | ||
1e59de90 | 1292 | template <typename Allocator, uintptr_t Bits> |
20effc67 TL |
1293 | struct require_member< |
1294 | boost::asio::io_context::basic_executor_type<Allocator, Bits>, | |
1295 | boost::asio::execution::blocking_t::possibly_t | |
1296 | > | |
1297 | { | |
1298 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1299 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | |
1300 | typedef boost::asio::io_context::basic_executor_type< | |
1301 | Allocator, Bits> result_type; | |
1302 | }; | |
1303 | ||
1e59de90 | 1304 | template <typename Allocator, uintptr_t Bits> |
20effc67 TL |
1305 | struct require_member< |
1306 | boost::asio::io_context::basic_executor_type<Allocator, Bits>, | |
1307 | boost::asio::execution::blocking_t::never_t | |
1308 | > | |
1309 | { | |
1310 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1311 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | |
1312 | typedef boost::asio::io_context::basic_executor_type< | |
1313 | Allocator, Bits> result_type; | |
1314 | }; | |
1315 | ||
1e59de90 | 1316 | template <typename Allocator, uintptr_t Bits> |
20effc67 TL |
1317 | struct require_member< |
1318 | boost::asio::io_context::basic_executor_type<Allocator, Bits>, | |
1319 | boost::asio::execution::relationship_t::fork_t | |
1320 | > | |
1321 | { | |
1322 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1323 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | |
1324 | typedef boost::asio::io_context::basic_executor_type< | |
1325 | Allocator, Bits> result_type; | |
1326 | }; | |
1327 | ||
1e59de90 | 1328 | template <typename Allocator, uintptr_t Bits> |
20effc67 TL |
1329 | struct require_member< |
1330 | boost::asio::io_context::basic_executor_type<Allocator, Bits>, | |
1331 | boost::asio::execution::relationship_t::continuation_t | |
1332 | > | |
1333 | { | |
1334 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1335 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | |
1336 | typedef boost::asio::io_context::basic_executor_type< | |
1337 | Allocator, Bits> result_type; | |
1338 | }; | |
1339 | ||
1e59de90 | 1340 | template <typename Allocator, uintptr_t Bits> |
20effc67 TL |
1341 | struct require_member< |
1342 | boost::asio::io_context::basic_executor_type<Allocator, Bits>, | |
1343 | boost::asio::execution::outstanding_work_t::tracked_t | |
1344 | > : boost::asio::detail::io_context_bits | |
1345 | { | |
1346 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1347 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | |
1348 | typedef boost::asio::io_context::basic_executor_type< | |
1349 | Allocator, Bits | outstanding_work_tracked> result_type; | |
1350 | }; | |
1351 | ||
1e59de90 | 1352 | template <typename Allocator, uintptr_t Bits> |
20effc67 TL |
1353 | struct require_member< |
1354 | boost::asio::io_context::basic_executor_type<Allocator, Bits>, | |
1355 | boost::asio::execution::outstanding_work_t::untracked_t | |
1356 | > : boost::asio::detail::io_context_bits | |
1357 | { | |
1358 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1359 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | |
1360 | typedef boost::asio::io_context::basic_executor_type< | |
1361 | Allocator, Bits & ~outstanding_work_tracked> result_type; | |
1362 | }; | |
1363 | ||
1e59de90 | 1364 | template <typename Allocator, uintptr_t Bits> |
20effc67 TL |
1365 | struct require_member< |
1366 | boost::asio::io_context::basic_executor_type<Allocator, Bits>, | |
1367 | boost::asio::execution::allocator_t<void> | |
1368 | > | |
1369 | { | |
1370 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1371 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | |
1372 | typedef boost::asio::io_context::basic_executor_type< | |
1373 | std::allocator<void>, Bits> result_type; | |
1374 | }; | |
1375 | ||
1e59de90 | 1376 | template <uintptr_t Bits, |
20effc67 TL |
1377 | typename Allocator, typename OtherAllocator> |
1378 | struct require_member< | |
1379 | boost::asio::io_context::basic_executor_type<Allocator, Bits>, | |
1380 | boost::asio::execution::allocator_t<OtherAllocator> | |
1381 | > | |
1382 | { | |
1383 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1384 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | |
1385 | typedef boost::asio::io_context::basic_executor_type< | |
1386 | OtherAllocator, Bits> result_type; | |
1387 | }; | |
1388 | ||
1389 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) | |
1390 | ||
1391 | #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) | |
1392 | ||
1e59de90 | 1393 | template <typename Allocator, uintptr_t Bits, typename Property> |
20effc67 TL |
1394 | struct query_static_constexpr_member< |
1395 | boost::asio::io_context::basic_executor_type<Allocator, Bits>, | |
1396 | Property, | |
1397 | typename boost::asio::enable_if< | |
1398 | boost::asio::is_convertible< | |
1399 | Property, | |
1400 | boost::asio::execution::outstanding_work_t | |
1401 | >::value | |
1402 | >::type | |
1403 | > : boost::asio::detail::io_context_bits | |
1404 | { | |
1405 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1406 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
1407 | typedef boost::asio::execution::outstanding_work_t result_type; | |
1408 | ||
1409 | static BOOST_ASIO_CONSTEXPR result_type value() BOOST_ASIO_NOEXCEPT | |
1410 | { | |
1411 | return (Bits & outstanding_work_tracked) | |
1412 | ? execution::outstanding_work_t(execution::outstanding_work.tracked) | |
1413 | : execution::outstanding_work_t(execution::outstanding_work.untracked); | |
1414 | } | |
1415 | }; | |
1416 | ||
1e59de90 | 1417 | template <typename Allocator, uintptr_t Bits, typename Property> |
20effc67 TL |
1418 | struct query_static_constexpr_member< |
1419 | boost::asio::io_context::basic_executor_type<Allocator, Bits>, | |
1420 | Property, | |
1421 | typename boost::asio::enable_if< | |
1422 | boost::asio::is_convertible< | |
1423 | Property, | |
1424 | boost::asio::execution::mapping_t | |
1425 | >::value | |
1426 | >::type | |
1427 | > | |
1428 | { | |
1429 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1430 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
1431 | typedef boost::asio::execution::mapping_t::thread_t result_type; | |
1432 | ||
1433 | static BOOST_ASIO_CONSTEXPR result_type value() BOOST_ASIO_NOEXCEPT | |
1434 | { | |
1435 | return result_type(); | |
1436 | } | |
1437 | }; | |
1438 | ||
1439 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) | |
1440 | ||
1441 | #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) | |
1442 | ||
1e59de90 | 1443 | template <typename Allocator, uintptr_t Bits, typename Property> |
20effc67 TL |
1444 | struct query_member< |
1445 | boost::asio::io_context::basic_executor_type<Allocator, Bits>, | |
1446 | Property, | |
1447 | typename boost::asio::enable_if< | |
1448 | boost::asio::is_convertible< | |
1449 | Property, | |
1450 | boost::asio::execution::blocking_t | |
1451 | >::value | |
1452 | >::type | |
1453 | > | |
1454 | { | |
1455 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1456 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
1457 | typedef boost::asio::execution::blocking_t result_type; | |
1458 | }; | |
1459 | ||
1e59de90 | 1460 | template <typename Allocator, uintptr_t Bits, typename Property> |
20effc67 TL |
1461 | struct query_member< |
1462 | boost::asio::io_context::basic_executor_type<Allocator, Bits>, | |
1463 | Property, | |
1464 | typename boost::asio::enable_if< | |
1465 | boost::asio::is_convertible< | |
1466 | Property, | |
1467 | boost::asio::execution::relationship_t | |
1468 | >::value | |
1469 | >::type | |
1470 | > | |
1471 | { | |
1472 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1473 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
1474 | typedef boost::asio::execution::relationship_t result_type; | |
1475 | }; | |
1476 | ||
1e59de90 | 1477 | template <typename Allocator, uintptr_t Bits> |
20effc67 TL |
1478 | struct query_member< |
1479 | boost::asio::io_context::basic_executor_type<Allocator, Bits>, | |
1480 | boost::asio::execution::context_t | |
1481 | > | |
1482 | { | |
1483 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1484 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
1485 | typedef boost::asio::io_context& result_type; | |
1486 | }; | |
1487 | ||
1e59de90 | 1488 | template <typename Allocator, uintptr_t Bits> |
20effc67 TL |
1489 | struct query_member< |
1490 | boost::asio::io_context::basic_executor_type<Allocator, Bits>, | |
1491 | boost::asio::execution::allocator_t<void> | |
1492 | > | |
1493 | { | |
1494 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1495 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
1496 | typedef Allocator result_type; | |
1497 | }; | |
1498 | ||
1e59de90 | 1499 | template <typename Allocator, uintptr_t Bits, typename OtherAllocator> |
20effc67 TL |
1500 | struct query_member< |
1501 | boost::asio::io_context::basic_executor_type<Allocator, Bits>, | |
1502 | boost::asio::execution::allocator_t<OtherAllocator> | |
1503 | > | |
1504 | { | |
1505 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1506 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
1507 | typedef Allocator result_type; | |
1508 | }; | |
1509 | ||
1510 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) | |
1511 | ||
1512 | } // namespace traits | |
1513 | ||
1e59de90 TL |
1514 | namespace execution { |
1515 | ||
1516 | template <> | |
1517 | struct is_executor<io_context> : false_type | |
1518 | { | |
1519 | }; | |
1520 | ||
1521 | } // namespace execution | |
1522 | ||
20effc67 TL |
1523 | #endif // !defined(GENERATING_DOCUMENTATION) |
1524 | ||
b32b8144 FG |
1525 | } // namespace asio |
1526 | } // namespace boost | |
1527 | ||
1528 | #include <boost/asio/detail/pop_options.hpp> | |
1529 | ||
1530 | #include <boost/asio/impl/io_context.hpp> | |
1531 | #if defined(BOOST_ASIO_HEADER_ONLY) | |
1532 | # include <boost/asio/impl/io_context.ipp> | |
1533 | #endif // defined(BOOST_ASIO_HEADER_ONLY) | |
1534 | ||
1535 | // If both io_context.hpp and strand.hpp have been included, automatically | |
1536 | // include the header file needed for the io_context::strand class. | |
1537 | #if !defined(BOOST_ASIO_NO_EXTENSIONS) | |
1538 | # if defined(BOOST_ASIO_STRAND_HPP) | |
1539 | # include <boost/asio/io_context_strand.hpp> | |
1540 | # endif // defined(BOOST_ASIO_STRAND_HPP) | |
1541 | #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) | |
1542 | ||
1543 | #endif // BOOST_ASIO_IO_CONTEXT_HPP |