]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/asio/io_context.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / asio / io_context.hpp
CommitLineData
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
49namespace boost {
50namespace asio {
51
52namespace 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 */
195class io_context
196 : public execution_context
197{
198private:
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
204public:
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
621private:
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
649namespace detail {
650
651} // namespace detail
652
653/// Executor implementation type used to submit functions to an io_context.
1e59de90
TL
654template <typename Allocator, uintptr_t Bits>
655class io_context::basic_executor_type :
656 detail::io_context_bits, Allocator
b32b8144
FG
657{
658public:
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)
700private:
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)
845private:
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 973public:
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)
1004private:
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 1021public:
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
1098private:
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 */
1148class io_context::work
1149{
1150public:
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
1178private:
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.
1188class io_context::service
1189 : public execution_context::service
1190{
1191public:
1192 /// Get the io_context object that owns the service.
1193 boost::asio::io_context& get_io_context();
1194
b32b8144
FG
1195private:
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
1225protected:
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
1236namespace detail {
1237
1238// Special service base class to keep classes header-file only.
1239template <typename Type>
1240class service_base
1241 : public boost::asio::io_context::service
1242{
1243public:
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
1253template <typename Type>
1254boost::asio::detail::service_id<Type> service_base<Type>::id;
1255
1256} // namespace detail
20effc67
TL
1257
1258#if !defined(GENERATING_DOCUMENTATION)
1259
1260namespace traits {
1261
1262#if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
1263
1e59de90 1264template <typename Allocator, uintptr_t Bits>
20effc67
TL
1265struct 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 1277template <typename Allocator, uintptr_t Bits, typename Function>
20effc67
TL
1278struct 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 1292template <typename Allocator, uintptr_t Bits>
20effc67
TL
1293struct 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 1304template <typename Allocator, uintptr_t Bits>
20effc67
TL
1305struct 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 1316template <typename Allocator, uintptr_t Bits>
20effc67
TL
1317struct 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 1328template <typename Allocator, uintptr_t Bits>
20effc67
TL
1329struct 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 1340template <typename Allocator, uintptr_t Bits>
20effc67
TL
1341struct 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 1352template <typename Allocator, uintptr_t Bits>
20effc67
TL
1353struct 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 1364template <typename Allocator, uintptr_t Bits>
20effc67
TL
1365struct 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 1376template <uintptr_t Bits,
20effc67
TL
1377 typename Allocator, typename OtherAllocator>
1378struct 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 1393template <typename Allocator, uintptr_t Bits, typename Property>
20effc67
TL
1394struct 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 1417template <typename Allocator, uintptr_t Bits, typename Property>
20effc67
TL
1418struct 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 1443template <typename Allocator, uintptr_t Bits, typename Property>
20effc67
TL
1444struct 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 1460template <typename Allocator, uintptr_t Bits, typename Property>
20effc67
TL
1461struct 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 1477template <typename Allocator, uintptr_t Bits>
20effc67
TL
1478struct 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 1488template <typename Allocator, uintptr_t Bits>
20effc67
TL
1489struct 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 1499template <typename Allocator, uintptr_t Bits, typename OtherAllocator>
20effc67
TL
1500struct 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
1514namespace execution {
1515
1516template <>
1517struct 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