|
||||
File indexing completed on 2025-01-18 09:29:10
0001 // 0002 // io_context.hpp 0003 // ~~~~~~~~~~~~~~ 0004 // 0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) 0006 // 0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying 0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 0009 // 0010 0011 #ifndef BOOST_ASIO_IO_CONTEXT_HPP 0012 #define BOOST_ASIO_IO_CONTEXT_HPP 0013 0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 0015 # pragma once 0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 0017 0018 #include <boost/asio/detail/config.hpp> 0019 #include <cstddef> 0020 #include <stdexcept> 0021 #include <typeinfo> 0022 #include <boost/asio/async_result.hpp> 0023 #include <boost/asio/detail/chrono.hpp> 0024 #include <boost/asio/detail/concurrency_hint.hpp> 0025 #include <boost/asio/detail/cstdint.hpp> 0026 #include <boost/asio/detail/wrapped_handler.hpp> 0027 #include <boost/system/error_code.hpp> 0028 #include <boost/asio/execution.hpp> 0029 #include <boost/asio/execution_context.hpp> 0030 0031 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) 0032 # include <boost/asio/detail/winsock_init.hpp> 0033 #elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \ 0034 || defined(__osf__) 0035 # include <boost/asio/detail/signal_init.hpp> 0036 #endif 0037 0038 #if defined(BOOST_ASIO_HAS_IOCP) 0039 # include <boost/asio/detail/win_iocp_io_context.hpp> 0040 #else 0041 # include <boost/asio/detail/scheduler.hpp> 0042 #endif 0043 0044 #include <boost/asio/detail/push_options.hpp> 0045 0046 namespace boost { 0047 namespace asio { 0048 0049 namespace detail { 0050 #if defined(BOOST_ASIO_HAS_IOCP) 0051 typedef win_iocp_io_context io_context_impl; 0052 class win_iocp_overlapped_ptr; 0053 #else 0054 typedef scheduler io_context_impl; 0055 #endif 0056 0057 struct io_context_bits 0058 { 0059 static constexpr uintptr_t blocking_never = 1; 0060 static constexpr uintptr_t relationship_continuation = 2; 0061 static constexpr uintptr_t outstanding_work_tracked = 4; 0062 static constexpr uintptr_t runtime_bits = 3; 0063 }; 0064 } // namespace detail 0065 0066 /// Provides core I/O functionality. 0067 /** 0068 * The io_context class provides the core I/O functionality for users of the 0069 * asynchronous I/O objects, including: 0070 * 0071 * @li boost::asio::ip::tcp::socket 0072 * @li boost::asio::ip::tcp::acceptor 0073 * @li boost::asio::ip::udp::socket 0074 * @li boost::asio::deadline_timer. 0075 * 0076 * The io_context class also includes facilities intended for developers of 0077 * custom asynchronous services. 0078 * 0079 * @par Thread Safety 0080 * @e Distinct @e objects: Safe.@n 0081 * @e Shared @e objects: Safe, with the specific exceptions of the restart() 0082 * and notify_fork() functions. Calling restart() while there are unfinished 0083 * run(), run_one(), run_for(), run_until(), poll() or poll_one() calls results 0084 * in undefined behaviour. The notify_fork() function should not be called 0085 * while any io_context function, or any function on an I/O object that is 0086 * associated with the io_context, is being called in another thread. 0087 * 0088 * @par Concepts: 0089 * Dispatcher. 0090 * 0091 * @par Synchronous and asynchronous operations 0092 * 0093 * Synchronous operations on I/O objects implicitly run the io_context object 0094 * for an individual operation. The io_context functions run(), run_one(), 0095 * run_for(), run_until(), poll() or poll_one() must be called for the 0096 * io_context to perform asynchronous operations on behalf of a C++ program. 0097 * Notification that an asynchronous operation has completed is delivered by 0098 * invocation of the associated handler. Handlers are invoked only by a thread 0099 * that is currently calling any overload of run(), run_one(), run_for(), 0100 * run_until(), poll() or poll_one() for the io_context. 0101 * 0102 * @par Effect of exceptions thrown from handlers 0103 * 0104 * If an exception is thrown from a handler, the exception is allowed to 0105 * propagate through the throwing thread's invocation of run(), run_one(), 0106 * run_for(), run_until(), poll() or poll_one(). No other threads that are 0107 * calling any of these functions are affected. It is then the responsibility 0108 * of the application to catch the exception. 0109 * 0110 * After the exception has been caught, the run(), run_one(), run_for(), 0111 * run_until(), poll() or poll_one() call may be restarted @em without the need 0112 * for an intervening call to restart(). This allows the thread to rejoin the 0113 * io_context object's thread pool without impacting any other threads in the 0114 * pool. 0115 * 0116 * For example: 0117 * 0118 * @code 0119 * boost::asio::io_context io_context; 0120 * ... 0121 * for (;;) 0122 * { 0123 * try 0124 * { 0125 * io_context.run(); 0126 * break; // run() exited normally 0127 * } 0128 * catch (my_exception& e) 0129 * { 0130 * // Deal with exception as appropriate. 0131 * } 0132 * } 0133 * @endcode 0134 * 0135 * @par Submitting arbitrary tasks to the io_context 0136 * 0137 * To submit functions to the io_context, use the @ref boost::asio::dispatch, 0138 * @ref boost::asio::post or @ref boost::asio::defer free functions. 0139 * 0140 * For example: 0141 * 0142 * @code void my_task() 0143 * { 0144 * ... 0145 * } 0146 * 0147 * ... 0148 * 0149 * boost::asio::io_context io_context; 0150 * 0151 * // Submit a function to the io_context. 0152 * boost::asio::post(io_context, my_task); 0153 * 0154 * // Submit a lambda object to the io_context. 0155 * boost::asio::post(io_context, 0156 * []() 0157 * { 0158 * ... 0159 * }); 0160 * 0161 * // Run the io_context until it runs out of work. 0162 * io_context.run(); @endcode 0163 * 0164 * @par Stopping the io_context from running out of work 0165 * 0166 * Some applications may need to prevent an io_context object's run() call from 0167 * returning when there is no more work to do. For example, the io_context may 0168 * be being run in a background thread that is launched prior to the 0169 * application's asynchronous operations. The run() call may be kept running by 0170 * using the @ref make_work_guard function to create an object of type 0171 * boost::asio::executor_work_guard<io_context::executor_type>: 0172 * 0173 * @code boost::asio::io_context io_context; 0174 * boost::asio::executor_work_guard<boost::asio::io_context::executor_type> 0175 * = boost::asio::make_work_guard(io_context); 0176 * ... @endcode 0177 * 0178 * To effect a shutdown, the application will then need to call the io_context 0179 * object's stop() member function. This will cause the io_context run() call 0180 * to return as soon as possible, abandoning unfinished operations and without 0181 * permitting ready handlers to be dispatched. 0182 * 0183 * Alternatively, if the application requires that all operations and handlers 0184 * be allowed to finish normally, the work object may be explicitly reset. 0185 * 0186 * @code boost::asio::io_context io_context; 0187 * boost::asio::executor_work_guard<boost::asio::io_context::executor_type> 0188 * = boost::asio::make_work_guard(io_context); 0189 * ... 0190 * work.reset(); // Allow run() to exit. @endcode 0191 */ 0192 class io_context 0193 : public execution_context 0194 { 0195 private: 0196 typedef detail::io_context_impl impl_type; 0197 #if defined(BOOST_ASIO_HAS_IOCP) 0198 friend class detail::win_iocp_overlapped_ptr; 0199 #endif 0200 0201 #if !defined(BOOST_ASIO_NO_DEPRECATED) 0202 struct initiate_dispatch; 0203 struct initiate_post; 0204 #endif // !defined(BOOST_ASIO_NO_DEPRECATED) 0205 0206 public: 0207 template <typename Allocator, uintptr_t Bits> 0208 class basic_executor_type; 0209 0210 template <typename Allocator, uintptr_t Bits> 0211 friend class basic_executor_type; 0212 0213 /// Executor used to submit functions to an io_context. 0214 typedef basic_executor_type<std::allocator<void>, 0> executor_type; 0215 0216 #if !defined(BOOST_ASIO_NO_DEPRECATED) 0217 class work; 0218 friend class work; 0219 #endif // !defined(BOOST_ASIO_NO_DEPRECATED) 0220 0221 class service; 0222 0223 #if !defined(BOOST_ASIO_NO_EXTENSIONS) \ 0224 && !defined(BOOST_ASIO_NO_TS_EXECUTORS) 0225 class strand; 0226 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) 0227 // && !defined(BOOST_ASIO_NO_TS_EXECUTORS) 0228 0229 /// The type used to count the number of handlers executed by the context. 0230 typedef std::size_t count_type; 0231 0232 /// Constructor. 0233 BOOST_ASIO_DECL io_context(); 0234 0235 /// Constructor. 0236 /** 0237 * Construct with a hint about the required level of concurrency. 0238 * 0239 * @param concurrency_hint A suggestion to the implementation on how many 0240 * threads it should allow to run simultaneously. 0241 */ 0242 BOOST_ASIO_DECL explicit io_context(int concurrency_hint); 0243 0244 /// Destructor. 0245 /** 0246 * On destruction, the io_context performs the following sequence of 0247 * operations: 0248 * 0249 * @li For each service object @c svc in the io_context set, in reverse order 0250 * of the beginning of service object lifetime, performs 0251 * @c svc->shutdown(). 0252 * 0253 * @li Uninvoked handler objects that were scheduled for deferred invocation 0254 * on the io_context, or any associated strand, are destroyed. 0255 * 0256 * @li For each service object @c svc in the io_context set, in reverse order 0257 * of the beginning of service object lifetime, performs 0258 * <tt>delete static_cast<io_context::service*>(svc)</tt>. 0259 * 0260 * @note The destruction sequence described above permits programs to 0261 * simplify their resource management by using @c shared_ptr<>. Where an 0262 * object's lifetime is tied to the lifetime of a connection (or some other 0263 * sequence of asynchronous operations), a @c shared_ptr to the object would 0264 * be bound into the handlers for all asynchronous operations associated with 0265 * it. This works as follows: 0266 * 0267 * @li When a single connection ends, all associated asynchronous operations 0268 * complete. The corresponding handler objects are destroyed, and all 0269 * @c shared_ptr references to the objects are destroyed. 0270 * 0271 * @li To shut down the whole program, the io_context function stop() is 0272 * called to terminate any run() calls as soon as possible. The io_context 0273 * destructor defined above destroys all handlers, causing all @c shared_ptr 0274 * references to all connection objects to be destroyed. 0275 */ 0276 BOOST_ASIO_DECL ~io_context(); 0277 0278 /// Obtains the executor associated with the io_context. 0279 executor_type get_executor() noexcept; 0280 0281 /// Run the io_context object's event processing loop. 0282 /** 0283 * The run() function blocks until all work has finished and there are no 0284 * more handlers to be dispatched, or until the io_context has been stopped. 0285 * 0286 * Multiple threads may call the run() function to set up a pool of threads 0287 * from which the io_context may execute handlers. All threads that are 0288 * waiting in the pool are equivalent and the io_context may choose any one 0289 * of them to invoke a handler. 0290 * 0291 * A normal exit from the run() function implies that the io_context object 0292 * is stopped (the stopped() function returns @c true). Subsequent calls to 0293 * run(), run_one(), poll() or poll_one() will return immediately unless there 0294 * is a prior call to restart(). 0295 * 0296 * @return The number of handlers that were executed. 0297 * 0298 * @note Calling the run() function from a thread that is currently calling 0299 * one of run(), run_one(), run_for(), run_until(), poll() or poll_one() on 0300 * the same io_context object may introduce the potential for deadlock. It is 0301 * the caller's reponsibility to avoid this. 0302 * 0303 * The poll() function may also be used to dispatch ready handlers, but 0304 * without blocking. 0305 */ 0306 BOOST_ASIO_DECL count_type run(); 0307 0308 #if !defined(BOOST_ASIO_NO_DEPRECATED) 0309 /// (Deprecated: Use non-error_code overload.) Run the io_context object's 0310 /// event processing loop. 0311 /** 0312 * The run() function blocks until all work has finished and there are no 0313 * more handlers to be dispatched, or until the io_context has been stopped. 0314 * 0315 * Multiple threads may call the run() function to set up a pool of threads 0316 * from which the io_context may execute handlers. All threads that are 0317 * waiting in the pool are equivalent and the io_context may choose any one 0318 * of them to invoke a handler. 0319 * 0320 * A normal exit from the run() function implies that the io_context object 0321 * is stopped (the stopped() function returns @c true). Subsequent calls to 0322 * run(), run_one(), poll() or poll_one() will return immediately unless there 0323 * is a prior call to restart(). 0324 * 0325 * @param ec Set to indicate what error occurred, if any. 0326 * 0327 * @return The number of handlers that were executed. 0328 * 0329 * @note Calling the run() function from a thread that is currently calling 0330 * one of run(), run_one(), run_for(), run_until(), poll() or poll_one() on 0331 * the same io_context object may introduce the potential for deadlock. It is 0332 * the caller's reponsibility to avoid this. 0333 * 0334 * The poll() function may also be used to dispatch ready handlers, but 0335 * without blocking. 0336 */ 0337 BOOST_ASIO_DECL count_type run(boost::system::error_code& ec); 0338 #endif // !defined(BOOST_ASIO_NO_DEPRECATED) 0339 0340 /// Run the io_context object's event processing loop for a specified 0341 /// duration. 0342 /** 0343 * The run_for() function blocks until all work has finished and there are no 0344 * more handlers to be dispatched, until the io_context has been stopped, or 0345 * until the specified duration has elapsed. 0346 * 0347 * @param rel_time The duration for which the call may block. 0348 * 0349 * @return The number of handlers that were executed. 0350 */ 0351 template <typename Rep, typename Period> 0352 std::size_t run_for(const chrono::duration<Rep, Period>& rel_time); 0353 0354 /// Run the io_context object's event processing loop until a specified time. 0355 /** 0356 * The run_until() function blocks until all work has finished and there are 0357 * no more handlers to be dispatched, until the io_context has been stopped, 0358 * or until the specified time has been reached. 0359 * 0360 * @param abs_time The time point until which the call may block. 0361 * 0362 * @return The number of handlers that were executed. 0363 */ 0364 template <typename Clock, typename Duration> 0365 std::size_t run_until(const chrono::time_point<Clock, Duration>& abs_time); 0366 0367 /// Run the io_context object's event processing loop to execute at most one 0368 /// handler. 0369 /** 0370 * The run_one() function blocks until one handler has been dispatched, or 0371 * until the io_context has been stopped. 0372 * 0373 * @return The number of handlers that were executed. A zero return value 0374 * implies that the io_context object is stopped (the stopped() function 0375 * returns @c true). Subsequent calls to run(), run_one(), poll() or 0376 * poll_one() will return immediately unless there is a prior call to 0377 * restart(). 0378 * 0379 * @note Calling the run_one() function from a thread that is currently 0380 * calling one of run(), run_one(), run_for(), run_until(), poll() or 0381 * poll_one() on the same io_context object may introduce the potential for 0382 * deadlock. It is the caller's reponsibility to avoid this. 0383 */ 0384 BOOST_ASIO_DECL count_type run_one(); 0385 0386 #if !defined(BOOST_ASIO_NO_DEPRECATED) 0387 /// (Deprecated: Use non-error_code overload.) Run the io_context object's 0388 /// event processing loop to execute at most one handler. 0389 /** 0390 * The run_one() function blocks until one handler has been dispatched, or 0391 * until the io_context has been stopped. 0392 * 0393 * @return The number of handlers that were executed. A zero return value 0394 * implies that the io_context object is stopped (the stopped() function 0395 * returns @c true). Subsequent calls to run(), run_one(), poll() or 0396 * poll_one() will return immediately unless there is a prior call to 0397 * restart(). 0398 * 0399 * @return The number of handlers that were executed. 0400 * 0401 * @note Calling the run_one() function from a thread that is currently 0402 * calling one of run(), run_one(), run_for(), run_until(), poll() or 0403 * poll_one() on the same io_context object may introduce the potential for 0404 * deadlock. It is the caller's reponsibility to avoid this. 0405 */ 0406 BOOST_ASIO_DECL count_type run_one(boost::system::error_code& ec); 0407 #endif // !defined(BOOST_ASIO_NO_DEPRECATED) 0408 0409 /// Run the io_context object's event processing loop for a specified duration 0410 /// to execute at most one handler. 0411 /** 0412 * The run_one_for() function blocks until one handler has been dispatched, 0413 * until the io_context has been stopped, or until the specified duration has 0414 * elapsed. 0415 * 0416 * @param rel_time The duration for which the call may block. 0417 * 0418 * @return The number of handlers that were executed. 0419 */ 0420 template <typename Rep, typename Period> 0421 std::size_t run_one_for(const chrono::duration<Rep, Period>& rel_time); 0422 0423 /// Run the io_context object's event processing loop until a specified time 0424 /// to execute at most one handler. 0425 /** 0426 * The run_one_until() function blocks until one handler has been dispatched, 0427 * until the io_context has been stopped, or until the specified time has 0428 * been reached. 0429 * 0430 * @param abs_time The time point until which the call may block. 0431 * 0432 * @return The number of handlers that were executed. 0433 */ 0434 template <typename Clock, typename Duration> 0435 std::size_t run_one_until( 0436 const chrono::time_point<Clock, Duration>& abs_time); 0437 0438 /// Run the io_context object's event processing loop to execute ready 0439 /// handlers. 0440 /** 0441 * The poll() function runs handlers that are ready to run, without blocking, 0442 * until the io_context has been stopped or there are no more ready handlers. 0443 * 0444 * @return The number of handlers that were executed. 0445 */ 0446 BOOST_ASIO_DECL count_type poll(); 0447 0448 #if !defined(BOOST_ASIO_NO_DEPRECATED) 0449 /// (Deprecated: Use non-error_code overload.) Run the io_context object's 0450 /// event processing loop to execute ready handlers. 0451 /** 0452 * The poll() function runs handlers that are ready to run, without blocking, 0453 * until the io_context has been stopped or there are no more ready handlers. 0454 * 0455 * @param ec Set to indicate what error occurred, if any. 0456 * 0457 * @return The number of handlers that were executed. 0458 */ 0459 BOOST_ASIO_DECL count_type poll(boost::system::error_code& ec); 0460 #endif // !defined(BOOST_ASIO_NO_DEPRECATED) 0461 0462 /// Run the io_context object's event processing loop to execute one ready 0463 /// handler. 0464 /** 0465 * The poll_one() function runs at most one handler that is ready to run, 0466 * without blocking. 0467 * 0468 * @return The number of handlers that were executed. 0469 */ 0470 BOOST_ASIO_DECL count_type poll_one(); 0471 0472 #if !defined(BOOST_ASIO_NO_DEPRECATED) 0473 /// (Deprecated: Use non-error_code overload.) Run the io_context object's 0474 /// event processing loop to execute one ready handler. 0475 /** 0476 * The poll_one() function runs at most one handler that is ready to run, 0477 * without blocking. 0478 * 0479 * @param ec Set to indicate what error occurred, if any. 0480 * 0481 * @return The number of handlers that were executed. 0482 */ 0483 BOOST_ASIO_DECL count_type poll_one(boost::system::error_code& ec); 0484 #endif // !defined(BOOST_ASIO_NO_DEPRECATED) 0485 0486 /// Stop the io_context object's event processing loop. 0487 /** 0488 * This function does not block, but instead simply signals the io_context to 0489 * stop. All invocations of its run() or run_one() member functions should 0490 * return as soon as possible. Subsequent calls to run(), run_one(), poll() 0491 * or poll_one() will return immediately until restart() is called. 0492 */ 0493 BOOST_ASIO_DECL void stop(); 0494 0495 /// Determine whether the io_context object has been stopped. 0496 /** 0497 * This function is used to determine whether an io_context object has been 0498 * stopped, either through an explicit call to stop(), or due to running out 0499 * of work. When an io_context object is stopped, calls to run(), run_one(), 0500 * poll() or poll_one() will return immediately without invoking any 0501 * handlers. 0502 * 0503 * @return @c true if the io_context object is stopped, otherwise @c false. 0504 */ 0505 BOOST_ASIO_DECL bool stopped() const; 0506 0507 /// Restart the io_context in preparation for a subsequent run() invocation. 0508 /** 0509 * This function must be called prior to any second or later set of 0510 * invocations of the run(), run_one(), poll() or poll_one() functions when a 0511 * previous invocation of these functions returned due to the io_context 0512 * being stopped or running out of work. After a call to restart(), the 0513 * io_context object's stopped() function will return @c false. 0514 * 0515 * This function must not be called while there are any unfinished calls to 0516 * the run(), run_one(), poll() or poll_one() functions. 0517 */ 0518 BOOST_ASIO_DECL void restart(); 0519 0520 #if !defined(BOOST_ASIO_NO_DEPRECATED) 0521 /// (Deprecated: Use restart().) Reset the io_context in preparation for a 0522 /// subsequent run() invocation. 0523 /** 0524 * This function must be called prior to any second or later set of 0525 * invocations of the run(), run_one(), poll() or poll_one() functions when a 0526 * previous invocation of these functions returned due to the io_context 0527 * being stopped or running out of work. After a call to restart(), the 0528 * io_context object's stopped() function will return @c false. 0529 * 0530 * This function must not be called while there are any unfinished calls to 0531 * the run(), run_one(), poll() or poll_one() functions. 0532 */ 0533 void reset(); 0534 0535 /// (Deprecated: Use boost::asio::dispatch().) Request the io_context to 0536 /// invoke the given handler. 0537 /** 0538 * This function is used to ask the io_context to execute the given handler. 0539 * 0540 * The io_context guarantees that the handler will only be called in a thread 0541 * in which the run(), run_one(), poll() or poll_one() member functions is 0542 * currently being invoked. The handler may be executed inside this function 0543 * if the guarantee can be met. 0544 * 0545 * @param handler The handler to be called. The io_context will make 0546 * a copy of the handler object as required. The function signature of the 0547 * handler must be: @code void handler(); @endcode 0548 * 0549 * @note This function throws an exception only if: 0550 * 0551 * @li the handler's associated allocator; or 0552 * 0553 * @li the handler's copy constructor 0554 * 0555 * throws an exception. 0556 */ 0557 template <typename LegacyCompletionHandler> 0558 auto dispatch(LegacyCompletionHandler&& handler) 0559 -> decltype( 0560 async_initiate<LegacyCompletionHandler, void ()>( 0561 declval<initiate_dispatch>(), handler, this)); 0562 0563 /// (Deprecated: Use boost::asio::post().) Request the io_context to invoke 0564 /// the given handler and return immediately. 0565 /** 0566 * This function is used to ask the io_context to execute the given handler, 0567 * but without allowing the io_context to call the handler from inside this 0568 * function. 0569 * 0570 * The io_context guarantees that the handler will only be called in a thread 0571 * in which the run(), run_one(), poll() or poll_one() member functions is 0572 * currently being invoked. 0573 * 0574 * @param handler The handler to be called. The io_context will make 0575 * a copy of the handler object as required. The function signature of the 0576 * handler must be: @code void handler(); @endcode 0577 * 0578 * @note This function throws an exception only if: 0579 * 0580 * @li the handler's associated allocator; or 0581 * 0582 * @li the handler's copy constructor 0583 * 0584 * throws an exception. 0585 */ 0586 template <typename LegacyCompletionHandler> 0587 auto post(LegacyCompletionHandler&& handler) 0588 -> decltype( 0589 async_initiate<LegacyCompletionHandler, void ()>( 0590 declval<initiate_post>(), handler, this)); 0591 0592 /// (Deprecated: Use boost::asio::bind_executor().) Create a new handler that 0593 /// automatically dispatches the wrapped handler on the io_context. 0594 /** 0595 * This function is used to create a new handler function object that, when 0596 * invoked, will automatically pass the wrapped handler to the io_context 0597 * object's dispatch function. 0598 * 0599 * @param handler The handler to be wrapped. The io_context will make a copy 0600 * of the handler object as required. The function signature of the handler 0601 * must be: @code void handler(A1 a1, ... An an); @endcode 0602 * 0603 * @return A function object that, when invoked, passes the wrapped handler to 0604 * the io_context object's dispatch function. Given a function object with the 0605 * signature: 0606 * @code R f(A1 a1, ... An an); @endcode 0607 * If this function object is passed to the wrap function like so: 0608 * @code io_context.wrap(f); @endcode 0609 * then the return value is a function object with the signature 0610 * @code void g(A1 a1, ... An an); @endcode 0611 * that, when invoked, executes code equivalent to: 0612 * @code io_context.dispatch(boost::bind(f, a1, ... an)); @endcode 0613 */ 0614 template <typename Handler> 0615 #if defined(GENERATING_DOCUMENTATION) 0616 unspecified 0617 #else 0618 detail::wrapped_handler<io_context&, Handler> 0619 #endif 0620 wrap(Handler handler); 0621 #endif // !defined(BOOST_ASIO_NO_DEPRECATED) 0622 0623 private: 0624 io_context(const io_context&) = delete; 0625 io_context& operator=(const io_context&) = delete; 0626 0627 // Helper function to add the implementation. 0628 BOOST_ASIO_DECL impl_type& add_impl(impl_type* impl); 0629 0630 // Backwards compatible overload for use with services derived from 0631 // io_context::service. 0632 template <typename Service> 0633 friend Service& use_service(io_context& ioc); 0634 0635 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) 0636 detail::winsock_init<> init_; 0637 #elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \ 0638 || defined(__osf__) 0639 detail::signal_init<> init_; 0640 #endif 0641 0642 // The implementation. 0643 impl_type& impl_; 0644 }; 0645 0646 namespace detail { 0647 0648 } // namespace detail 0649 0650 /// Executor implementation type used to submit functions to an io_context. 0651 template <typename Allocator, uintptr_t Bits> 0652 class io_context::basic_executor_type : 0653 detail::io_context_bits, Allocator 0654 { 0655 public: 0656 /// Copy constructor. 0657 basic_executor_type(const basic_executor_type& other) noexcept 0658 : Allocator(static_cast<const Allocator&>(other)), 0659 target_(other.target_) 0660 { 0661 if (Bits & outstanding_work_tracked) 0662 if (context_ptr()) 0663 context_ptr()->impl_.work_started(); 0664 } 0665 0666 /// Move constructor. 0667 basic_executor_type(basic_executor_type&& other) noexcept 0668 : Allocator(static_cast<Allocator&&>(other)), 0669 target_(other.target_) 0670 { 0671 if (Bits & outstanding_work_tracked) 0672 other.target_ = 0; 0673 } 0674 0675 /// Destructor. 0676 ~basic_executor_type() noexcept 0677 { 0678 if (Bits & outstanding_work_tracked) 0679 if (context_ptr()) 0680 context_ptr()->impl_.work_finished(); 0681 } 0682 0683 /// Assignment operator. 0684 basic_executor_type& operator=(const basic_executor_type& other) noexcept; 0685 0686 /// Move assignment operator. 0687 basic_executor_type& operator=(basic_executor_type&& other) noexcept; 0688 0689 #if !defined(GENERATING_DOCUMENTATION) 0690 private: 0691 friend struct boost_asio_require_fn::impl; 0692 friend struct boost_asio_prefer_fn::impl; 0693 #endif // !defined(GENERATING_DOCUMENTATION) 0694 0695 /// Obtain an executor with the @c blocking.possibly property. 0696 /** 0697 * Do not call this function directly. It is intended for use with the 0698 * boost::asio::require customisation point. 0699 * 0700 * For example: 0701 * @code auto ex1 = my_io_context.get_executor(); 0702 * auto ex2 = boost::asio::require(ex1, 0703 * boost::asio::execution::blocking.possibly); @endcode 0704 */ 0705 constexpr basic_executor_type require(execution::blocking_t::possibly_t) const 0706 { 0707 return basic_executor_type(context_ptr(), 0708 *this, bits() & ~blocking_never); 0709 } 0710 0711 /// Obtain an executor with the @c blocking.never property. 0712 /** 0713 * Do not call this function directly. It is intended for use with the 0714 * boost::asio::require customisation point. 0715 * 0716 * For example: 0717 * @code auto ex1 = my_io_context.get_executor(); 0718 * auto ex2 = boost::asio::require(ex1, 0719 * boost::asio::execution::blocking.never); @endcode 0720 */ 0721 constexpr basic_executor_type require(execution::blocking_t::never_t) const 0722 { 0723 return basic_executor_type(context_ptr(), 0724 *this, bits() | blocking_never); 0725 } 0726 0727 /// Obtain an executor with the @c relationship.fork property. 0728 /** 0729 * Do not call this function directly. It is intended for use with the 0730 * boost::asio::require customisation point. 0731 * 0732 * For example: 0733 * @code auto ex1 = my_io_context.get_executor(); 0734 * auto ex2 = boost::asio::require(ex1, 0735 * boost::asio::execution::relationship.fork); @endcode 0736 */ 0737 constexpr basic_executor_type require(execution::relationship_t::fork_t) const 0738 { 0739 return basic_executor_type(context_ptr(), 0740 *this, bits() & ~relationship_continuation); 0741 } 0742 0743 /// Obtain an executor with the @c relationship.continuation property. 0744 /** 0745 * Do not call this function directly. It is intended for use with the 0746 * boost::asio::require customisation point. 0747 * 0748 * For example: 0749 * @code auto ex1 = my_io_context.get_executor(); 0750 * auto ex2 = boost::asio::require(ex1, 0751 * boost::asio::execution::relationship.continuation); @endcode 0752 */ 0753 constexpr basic_executor_type require( 0754 execution::relationship_t::continuation_t) const 0755 { 0756 return basic_executor_type(context_ptr(), 0757 *this, bits() | relationship_continuation); 0758 } 0759 0760 /// Obtain an executor with the @c outstanding_work.tracked property. 0761 /** 0762 * Do not call this function directly. It is intended for use with the 0763 * boost::asio::require customisation point. 0764 * 0765 * For example: 0766 * @code auto ex1 = my_io_context.get_executor(); 0767 * auto ex2 = boost::asio::require(ex1, 0768 * boost::asio::execution::outstanding_work.tracked); @endcode 0769 */ 0770 constexpr basic_executor_type<Allocator, 0771 BOOST_ASIO_UNSPECIFIED(Bits | outstanding_work_tracked)> 0772 require(execution::outstanding_work_t::tracked_t) const 0773 { 0774 return basic_executor_type<Allocator, Bits | outstanding_work_tracked>( 0775 context_ptr(), *this, bits()); 0776 } 0777 0778 /// Obtain an executor with the @c outstanding_work.untracked property. 0779 /** 0780 * Do not call this function directly. It is intended for use with the 0781 * boost::asio::require customisation point. 0782 * 0783 * For example: 0784 * @code auto ex1 = my_io_context.get_executor(); 0785 * auto ex2 = boost::asio::require(ex1, 0786 * boost::asio::execution::outstanding_work.untracked); @endcode 0787 */ 0788 constexpr basic_executor_type<Allocator, 0789 BOOST_ASIO_UNSPECIFIED(Bits & ~outstanding_work_tracked)> 0790 require(execution::outstanding_work_t::untracked_t) const 0791 { 0792 return basic_executor_type<Allocator, Bits & ~outstanding_work_tracked>( 0793 context_ptr(), *this, bits()); 0794 } 0795 0796 /// Obtain an executor with the specified @c allocator property. 0797 /** 0798 * Do not call this function directly. It is intended for use with the 0799 * boost::asio::require customisation point. 0800 * 0801 * For example: 0802 * @code auto ex1 = my_io_context.get_executor(); 0803 * auto ex2 = boost::asio::require(ex1, 0804 * boost::asio::execution::allocator(my_allocator)); @endcode 0805 */ 0806 template <typename OtherAllocator> 0807 constexpr basic_executor_type<OtherAllocator, Bits> 0808 require(execution::allocator_t<OtherAllocator> a) const 0809 { 0810 return basic_executor_type<OtherAllocator, Bits>( 0811 context_ptr(), a.value(), bits()); 0812 } 0813 0814 /// Obtain an executor with the default @c allocator property. 0815 /** 0816 * Do not call this function directly. It is intended for use with the 0817 * boost::asio::require customisation point. 0818 * 0819 * For example: 0820 * @code auto ex1 = my_io_context.get_executor(); 0821 * auto ex2 = boost::asio::require(ex1, 0822 * boost::asio::execution::allocator); @endcode 0823 */ 0824 constexpr basic_executor_type<std::allocator<void>, Bits> 0825 require(execution::allocator_t<void>) const 0826 { 0827 return basic_executor_type<std::allocator<void>, Bits>( 0828 context_ptr(), std::allocator<void>(), bits()); 0829 } 0830 0831 #if !defined(GENERATING_DOCUMENTATION) 0832 private: 0833 friend struct boost_asio_query_fn::impl; 0834 friend struct boost::asio::execution::detail::mapping_t<0>; 0835 friend struct boost::asio::execution::detail::outstanding_work_t<0>; 0836 #endif // !defined(GENERATING_DOCUMENTATION) 0837 0838 /// Query the current value of the @c mapping property. 0839 /** 0840 * Do not call this function directly. It is intended for use with the 0841 * boost::asio::query customisation point. 0842 * 0843 * For example: 0844 * @code auto ex = my_io_context.get_executor(); 0845 * if (boost::asio::query(ex, boost::asio::execution::mapping) 0846 * == boost::asio::execution::mapping.thread) 0847 * ... @endcode 0848 */ 0849 static constexpr execution::mapping_t query(execution::mapping_t) noexcept 0850 { 0851 return execution::mapping.thread; 0852 } 0853 0854 /// Query the current value of the @c context property. 0855 /** 0856 * Do not call this function directly. It is intended for use with the 0857 * boost::asio::query customisation point. 0858 * 0859 * For example: 0860 * @code auto ex = my_io_context.get_executor(); 0861 * boost::asio::io_context& ctx = boost::asio::query( 0862 * ex, boost::asio::execution::context); @endcode 0863 */ 0864 io_context& query(execution::context_t) const noexcept 0865 { 0866 return *context_ptr(); 0867 } 0868 0869 /// Query the current value of the @c blocking property. 0870 /** 0871 * Do not call this function directly. It is intended for use with the 0872 * boost::asio::query customisation point. 0873 * 0874 * For example: 0875 * @code auto ex = my_io_context.get_executor(); 0876 * if (boost::asio::query(ex, boost::asio::execution::blocking) 0877 * == boost::asio::execution::blocking.always) 0878 * ... @endcode 0879 */ 0880 constexpr execution::blocking_t query(execution::blocking_t) const noexcept 0881 { 0882 return (bits() & blocking_never) 0883 ? execution::blocking_t(execution::blocking.never) 0884 : execution::blocking_t(execution::blocking.possibly); 0885 } 0886 0887 /// Query the current value of the @c relationship property. 0888 /** 0889 * Do not call this function directly. It is intended for use with the 0890 * boost::asio::query customisation point. 0891 * 0892 * For example: 0893 * @code auto ex = my_io_context.get_executor(); 0894 * if (boost::asio::query(ex, boost::asio::execution::relationship) 0895 * == boost::asio::execution::relationship.continuation) 0896 * ... @endcode 0897 */ 0898 constexpr execution::relationship_t query( 0899 execution::relationship_t) const noexcept 0900 { 0901 return (bits() & relationship_continuation) 0902 ? execution::relationship_t(execution::relationship.continuation) 0903 : execution::relationship_t(execution::relationship.fork); 0904 } 0905 0906 /// Query the current value of the @c outstanding_work property. 0907 /** 0908 * Do not call this function directly. It is intended for use with the 0909 * boost::asio::query customisation point. 0910 * 0911 * For example: 0912 * @code auto ex = my_io_context.get_executor(); 0913 * if (boost::asio::query(ex, boost::asio::execution::outstanding_work) 0914 * == boost::asio::execution::outstanding_work.tracked) 0915 * ... @endcode 0916 */ 0917 static constexpr execution::outstanding_work_t query( 0918 execution::outstanding_work_t) noexcept 0919 { 0920 return (Bits & outstanding_work_tracked) 0921 ? execution::outstanding_work_t(execution::outstanding_work.tracked) 0922 : execution::outstanding_work_t(execution::outstanding_work.untracked); 0923 } 0924 0925 /// Query the current value of the @c allocator property. 0926 /** 0927 * Do not call this function directly. It is intended for use with the 0928 * boost::asio::query customisation point. 0929 * 0930 * For example: 0931 * @code auto ex = my_io_context.get_executor(); 0932 * auto alloc = boost::asio::query(ex, 0933 * boost::asio::execution::allocator); @endcode 0934 */ 0935 template <typename OtherAllocator> 0936 constexpr Allocator query( 0937 execution::allocator_t<OtherAllocator>) const noexcept 0938 { 0939 return static_cast<const Allocator&>(*this); 0940 } 0941 0942 /// Query the current value of the @c allocator property. 0943 /** 0944 * Do not call this function directly. It is intended for use with the 0945 * boost::asio::query customisation point. 0946 * 0947 * For example: 0948 * @code auto ex = my_io_context.get_executor(); 0949 * auto alloc = boost::asio::query(ex, 0950 * boost::asio::execution::allocator); @endcode 0951 */ 0952 constexpr Allocator query(execution::allocator_t<void>) const noexcept 0953 { 0954 return static_cast<const Allocator&>(*this); 0955 } 0956 0957 public: 0958 /// Determine whether the io_context is running in the current thread. 0959 /** 0960 * @return @c true if the current thread is running the io_context. Otherwise 0961 * returns @c false. 0962 */ 0963 bool running_in_this_thread() const noexcept; 0964 0965 /// Compare two executors for equality. 0966 /** 0967 * Two executors are equal if they refer to the same underlying io_context. 0968 */ 0969 friend bool operator==(const basic_executor_type& a, 0970 const basic_executor_type& b) noexcept 0971 { 0972 return a.target_ == b.target_ 0973 && static_cast<const Allocator&>(a) == static_cast<const Allocator&>(b); 0974 } 0975 0976 /// Compare two executors for inequality. 0977 /** 0978 * Two executors are equal if they refer to the same underlying io_context. 0979 */ 0980 friend bool operator!=(const basic_executor_type& a, 0981 const basic_executor_type& b) noexcept 0982 { 0983 return a.target_ != b.target_ 0984 || static_cast<const Allocator&>(a) != static_cast<const Allocator&>(b); 0985 } 0986 0987 /// Execution function. 0988 template <typename Function> 0989 void execute(Function&& f) const; 0990 0991 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS) 0992 public: 0993 /// Obtain the underlying execution context. 0994 io_context& context() const noexcept; 0995 0996 /// Inform the io_context that it has some outstanding work to do. 0997 /** 0998 * This function is used to inform the io_context that some work has begun. 0999 * This ensures that the io_context's run() and run_one() functions do not 1000 * exit while the work is underway. 1001 */ 1002 void on_work_started() const noexcept; 1003 1004 /// Inform the io_context that some work is no longer outstanding. 1005 /** 1006 * This function is used to inform the io_context that some work has 1007 * finished. Once the count of unfinished work reaches zero, the io_context 1008 * is stopped and the run() and run_one() functions may exit. 1009 */ 1010 void on_work_finished() const noexcept; 1011 1012 /// Request the io_context to invoke the given function object. 1013 /** 1014 * This function is used to ask the io_context to execute the given function 1015 * object. If the current thread is running the io_context, @c dispatch() 1016 * executes the function before returning. Otherwise, the function will be 1017 * scheduled to run on the io_context. 1018 * 1019 * @param f The function object to be called. The executor will make a copy 1020 * of the handler object as required. The function signature of the function 1021 * object must be: @code void function(); @endcode 1022 * 1023 * @param a An allocator that may be used by the executor to allocate the 1024 * internal storage needed for function invocation. 1025 */ 1026 template <typename Function, typename OtherAllocator> 1027 void dispatch(Function&& f, const OtherAllocator& a) const; 1028 1029 /// Request the io_context to invoke the given function object. 1030 /** 1031 * This function is used to ask the io_context to execute the given function 1032 * object. The function object will never be executed inside @c post(). 1033 * Instead, it will be scheduled to run on the io_context. 1034 * 1035 * @param f The function object to be called. The executor will make a copy 1036 * of the handler object as required. The function signature of the function 1037 * object must be: @code void function(); @endcode 1038 * 1039 * @param a An allocator that may be used by the executor to allocate the 1040 * internal storage needed for function invocation. 1041 */ 1042 template <typename Function, typename OtherAllocator> 1043 void post(Function&& f, const OtherAllocator& a) const; 1044 1045 /// Request the io_context to invoke the given function object. 1046 /** 1047 * This function is used to ask the io_context to execute the given function 1048 * object. The function object will never be executed inside @c defer(). 1049 * Instead, it will be scheduled to run on the io_context. 1050 * 1051 * If the current thread belongs to the io_context, @c defer() will delay 1052 * scheduling the function object until the current thread returns control to 1053 * the pool. 1054 * 1055 * @param f The function object to be called. The executor will make a copy 1056 * of the handler object as required. The function signature of the function 1057 * object must be: @code void function(); @endcode 1058 * 1059 * @param a An allocator that may be used by the executor to allocate the 1060 * internal storage needed for function invocation. 1061 */ 1062 template <typename Function, typename OtherAllocator> 1063 void defer(Function&& f, const OtherAllocator& a) const; 1064 #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS) 1065 1066 private: 1067 friend class io_context; 1068 template <typename, uintptr_t> friend class basic_executor_type; 1069 1070 // Constructor used by io_context::get_executor(). 1071 explicit basic_executor_type(io_context& i) noexcept 1072 : Allocator(), 1073 target_(reinterpret_cast<uintptr_t>(&i)) 1074 { 1075 if (Bits & outstanding_work_tracked) 1076 context_ptr()->impl_.work_started(); 1077 } 1078 1079 // Constructor used by require(). 1080 basic_executor_type(io_context* i, 1081 const Allocator& a, uintptr_t bits) noexcept 1082 : Allocator(a), 1083 target_(reinterpret_cast<uintptr_t>(i) | bits) 1084 { 1085 if (Bits & outstanding_work_tracked) 1086 if (context_ptr()) 1087 context_ptr()->impl_.work_started(); 1088 } 1089 1090 io_context* context_ptr() const noexcept 1091 { 1092 return reinterpret_cast<io_context*>(target_ & ~runtime_bits); 1093 } 1094 1095 uintptr_t bits() const noexcept 1096 { 1097 return target_ & runtime_bits; 1098 } 1099 1100 // The underlying io_context and runtime bits. 1101 uintptr_t target_; 1102 }; 1103 1104 #if !defined(BOOST_ASIO_NO_DEPRECATED) 1105 /// (Deprecated: Use executor_work_guard.) Class to inform the io_context when 1106 /// it has work to do. 1107 /** 1108 * The work class is used to inform the io_context when work starts and 1109 * finishes. This ensures that the io_context object's run() function will not 1110 * exit while work is underway, and that it does exit when there is no 1111 * unfinished work remaining. 1112 * 1113 * The work class is copy-constructible so that it may be used as a data member 1114 * in a handler class. It is not assignable. 1115 */ 1116 class io_context::work 1117 { 1118 public: 1119 /// Constructor notifies the io_context that work is starting. 1120 /** 1121 * The constructor is used to inform the io_context that some work has begun. 1122 * This ensures that the io_context object's run() function will not exit 1123 * while the work is underway. 1124 */ 1125 explicit work(boost::asio::io_context& io_context); 1126 1127 /// Copy constructor notifies the io_context that work is starting. 1128 /** 1129 * The constructor is used to inform the io_context that some work has begun. 1130 * This ensures that the io_context object's run() function will not exit 1131 * while the work is underway. 1132 */ 1133 work(const work& other); 1134 1135 /// Destructor notifies the io_context that the work is complete. 1136 /** 1137 * The destructor is used to inform the io_context that some work has 1138 * finished. Once the count of unfinished work reaches zero, the io_context 1139 * object's run() function is permitted to exit. 1140 */ 1141 ~work(); 1142 1143 /// Get the io_context associated with the work. 1144 boost::asio::io_context& get_io_context(); 1145 1146 private: 1147 // Prevent assignment. 1148 void operator=(const work& other); 1149 1150 // The io_context implementation. 1151 detail::io_context_impl& io_context_impl_; 1152 }; 1153 #endif // !defined(BOOST_ASIO_NO_DEPRECATED) 1154 1155 /// Base class for all io_context services. 1156 class io_context::service 1157 : public execution_context::service 1158 { 1159 public: 1160 /// Get the io_context object that owns the service. 1161 boost::asio::io_context& get_io_context(); 1162 1163 private: 1164 /// Destroy all user-defined handler objects owned by the service. 1165 BOOST_ASIO_DECL virtual void shutdown(); 1166 1167 #if !defined(BOOST_ASIO_NO_DEPRECATED) 1168 /// (Deprecated: Use shutdown().) Destroy all user-defined handler objects 1169 /// owned by the service. 1170 BOOST_ASIO_DECL virtual void shutdown_service(); 1171 #endif // !defined(BOOST_ASIO_NO_DEPRECATED) 1172 1173 /// Handle notification of a fork-related event to perform any necessary 1174 /// housekeeping. 1175 /** 1176 * This function is not a pure virtual so that services only have to 1177 * implement it if necessary. The default implementation does nothing. 1178 */ 1179 BOOST_ASIO_DECL virtual void notify_fork( 1180 execution_context::fork_event event); 1181 1182 #if !defined(BOOST_ASIO_NO_DEPRECATED) 1183 /// (Deprecated: Use notify_fork().) Handle notification of a fork-related 1184 /// event to perform any necessary housekeeping. 1185 /** 1186 * This function is not a pure virtual so that services only have to 1187 * implement it if necessary. The default implementation does nothing. 1188 */ 1189 BOOST_ASIO_DECL virtual void fork_service( 1190 execution_context::fork_event event); 1191 #endif // !defined(BOOST_ASIO_NO_DEPRECATED) 1192 1193 protected: 1194 /// Constructor. 1195 /** 1196 * @param owner The io_context object that owns the service. 1197 */ 1198 BOOST_ASIO_DECL service(boost::asio::io_context& owner); 1199 1200 /// Destructor. 1201 BOOST_ASIO_DECL virtual ~service(); 1202 }; 1203 1204 namespace detail { 1205 1206 // Special service base class to keep classes header-file only. 1207 template <typename Type> 1208 class service_base 1209 : public boost::asio::io_context::service 1210 { 1211 public: 1212 static boost::asio::detail::service_id<Type> id; 1213 1214 // Constructor. 1215 service_base(boost::asio::io_context& io_context) 1216 : boost::asio::io_context::service(io_context) 1217 { 1218 } 1219 }; 1220 1221 template <typename Type> 1222 boost::asio::detail::service_id<Type> service_base<Type>::id; 1223 1224 } // namespace detail 1225 1226 #if !defined(GENERATING_DOCUMENTATION) 1227 1228 namespace traits { 1229 1230 #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) 1231 1232 template <typename Allocator, uintptr_t Bits> 1233 struct equality_comparable< 1234 boost::asio::io_context::basic_executor_type<Allocator, Bits> 1235 > 1236 { 1237 static constexpr bool is_valid = true; 1238 static constexpr bool is_noexcept = true; 1239 }; 1240 1241 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) 1242 1243 #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) 1244 1245 template <typename Allocator, uintptr_t Bits, typename Function> 1246 struct execute_member< 1247 boost::asio::io_context::basic_executor_type<Allocator, Bits>, 1248 Function 1249 > 1250 { 1251 static constexpr bool is_valid = true; 1252 static constexpr bool is_noexcept = false; 1253 typedef void result_type; 1254 }; 1255 1256 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) 1257 1258 #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) 1259 1260 template <typename Allocator, uintptr_t Bits> 1261 struct require_member< 1262 boost::asio::io_context::basic_executor_type<Allocator, Bits>, 1263 boost::asio::execution::blocking_t::possibly_t 1264 > 1265 { 1266 static constexpr bool is_valid = true; 1267 static constexpr bool is_noexcept = false; 1268 typedef boost::asio::io_context::basic_executor_type< 1269 Allocator, Bits> result_type; 1270 }; 1271 1272 template <typename Allocator, uintptr_t Bits> 1273 struct require_member< 1274 boost::asio::io_context::basic_executor_type<Allocator, Bits>, 1275 boost::asio::execution::blocking_t::never_t 1276 > 1277 { 1278 static constexpr bool is_valid = true; 1279 static constexpr bool is_noexcept = false; 1280 typedef boost::asio::io_context::basic_executor_type< 1281 Allocator, Bits> result_type; 1282 }; 1283 1284 template <typename Allocator, uintptr_t Bits> 1285 struct require_member< 1286 boost::asio::io_context::basic_executor_type<Allocator, Bits>, 1287 boost::asio::execution::relationship_t::fork_t 1288 > 1289 { 1290 static constexpr bool is_valid = true; 1291 static constexpr bool is_noexcept = false; 1292 typedef boost::asio::io_context::basic_executor_type< 1293 Allocator, Bits> result_type; 1294 }; 1295 1296 template <typename Allocator, uintptr_t Bits> 1297 struct require_member< 1298 boost::asio::io_context::basic_executor_type<Allocator, Bits>, 1299 boost::asio::execution::relationship_t::continuation_t 1300 > 1301 { 1302 static constexpr bool is_valid = true; 1303 static constexpr bool is_noexcept = false; 1304 typedef boost::asio::io_context::basic_executor_type< 1305 Allocator, Bits> result_type; 1306 }; 1307 1308 template <typename Allocator, uintptr_t Bits> 1309 struct require_member< 1310 boost::asio::io_context::basic_executor_type<Allocator, Bits>, 1311 boost::asio::execution::outstanding_work_t::tracked_t 1312 > : boost::asio::detail::io_context_bits 1313 { 1314 static constexpr bool is_valid = true; 1315 static constexpr bool is_noexcept = false; 1316 typedef boost::asio::io_context::basic_executor_type< 1317 Allocator, Bits | outstanding_work_tracked> result_type; 1318 }; 1319 1320 template <typename Allocator, uintptr_t Bits> 1321 struct require_member< 1322 boost::asio::io_context::basic_executor_type<Allocator, Bits>, 1323 boost::asio::execution::outstanding_work_t::untracked_t 1324 > : boost::asio::detail::io_context_bits 1325 { 1326 static constexpr bool is_valid = true; 1327 static constexpr bool is_noexcept = false; 1328 typedef boost::asio::io_context::basic_executor_type< 1329 Allocator, Bits & ~outstanding_work_tracked> result_type; 1330 }; 1331 1332 template <typename Allocator, uintptr_t Bits> 1333 struct require_member< 1334 boost::asio::io_context::basic_executor_type<Allocator, Bits>, 1335 boost::asio::execution::allocator_t<void> 1336 > 1337 { 1338 static constexpr bool is_valid = true; 1339 static constexpr bool is_noexcept = false; 1340 typedef boost::asio::io_context::basic_executor_type< 1341 std::allocator<void>, Bits> result_type; 1342 }; 1343 1344 template <uintptr_t Bits, 1345 typename Allocator, typename OtherAllocator> 1346 struct require_member< 1347 boost::asio::io_context::basic_executor_type<Allocator, Bits>, 1348 boost::asio::execution::allocator_t<OtherAllocator> 1349 > 1350 { 1351 static constexpr bool is_valid = true; 1352 static constexpr bool is_noexcept = false; 1353 typedef boost::asio::io_context::basic_executor_type< 1354 OtherAllocator, Bits> result_type; 1355 }; 1356 1357 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) 1358 1359 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) 1360 1361 template <typename Allocator, uintptr_t Bits, typename Property> 1362 struct query_static_constexpr_member< 1363 boost::asio::io_context::basic_executor_type<Allocator, Bits>, 1364 Property, 1365 typename boost::asio::enable_if< 1366 boost::asio::is_convertible< 1367 Property, 1368 boost::asio::execution::outstanding_work_t 1369 >::value 1370 >::type 1371 > : boost::asio::detail::io_context_bits 1372 { 1373 static constexpr bool is_valid = true; 1374 static constexpr bool is_noexcept = true; 1375 typedef boost::asio::execution::outstanding_work_t result_type; 1376 1377 static constexpr result_type value() noexcept 1378 { 1379 return (Bits & outstanding_work_tracked) 1380 ? execution::outstanding_work_t(execution::outstanding_work.tracked) 1381 : execution::outstanding_work_t(execution::outstanding_work.untracked); 1382 } 1383 }; 1384 1385 template <typename Allocator, uintptr_t Bits, typename Property> 1386 struct query_static_constexpr_member< 1387 boost::asio::io_context::basic_executor_type<Allocator, Bits>, 1388 Property, 1389 typename boost::asio::enable_if< 1390 boost::asio::is_convertible< 1391 Property, 1392 boost::asio::execution::mapping_t 1393 >::value 1394 >::type 1395 > 1396 { 1397 static constexpr bool is_valid = true; 1398 static constexpr bool is_noexcept = true; 1399 typedef boost::asio::execution::mapping_t::thread_t result_type; 1400 1401 static constexpr result_type value() noexcept 1402 { 1403 return result_type(); 1404 } 1405 }; 1406 1407 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) 1408 1409 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) 1410 1411 template <typename Allocator, uintptr_t Bits, typename Property> 1412 struct query_member< 1413 boost::asio::io_context::basic_executor_type<Allocator, Bits>, 1414 Property, 1415 typename boost::asio::enable_if< 1416 boost::asio::is_convertible< 1417 Property, 1418 boost::asio::execution::blocking_t 1419 >::value 1420 >::type 1421 > 1422 { 1423 static constexpr bool is_valid = true; 1424 static constexpr bool is_noexcept = true; 1425 typedef boost::asio::execution::blocking_t result_type; 1426 }; 1427 1428 template <typename Allocator, uintptr_t Bits, typename Property> 1429 struct query_member< 1430 boost::asio::io_context::basic_executor_type<Allocator, Bits>, 1431 Property, 1432 typename boost::asio::enable_if< 1433 boost::asio::is_convertible< 1434 Property, 1435 boost::asio::execution::relationship_t 1436 >::value 1437 >::type 1438 > 1439 { 1440 static constexpr bool is_valid = true; 1441 static constexpr bool is_noexcept = true; 1442 typedef boost::asio::execution::relationship_t result_type; 1443 }; 1444 1445 template <typename Allocator, uintptr_t Bits> 1446 struct query_member< 1447 boost::asio::io_context::basic_executor_type<Allocator, Bits>, 1448 boost::asio::execution::context_t 1449 > 1450 { 1451 static constexpr bool is_valid = true; 1452 static constexpr bool is_noexcept = true; 1453 typedef boost::asio::io_context& result_type; 1454 }; 1455 1456 template <typename Allocator, uintptr_t Bits> 1457 struct query_member< 1458 boost::asio::io_context::basic_executor_type<Allocator, Bits>, 1459 boost::asio::execution::allocator_t<void> 1460 > 1461 { 1462 static constexpr bool is_valid = true; 1463 static constexpr bool is_noexcept = true; 1464 typedef Allocator result_type; 1465 }; 1466 1467 template <typename Allocator, uintptr_t Bits, typename OtherAllocator> 1468 struct query_member< 1469 boost::asio::io_context::basic_executor_type<Allocator, Bits>, 1470 boost::asio::execution::allocator_t<OtherAllocator> 1471 > 1472 { 1473 static constexpr bool is_valid = true; 1474 static constexpr bool is_noexcept = true; 1475 typedef Allocator result_type; 1476 }; 1477 1478 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) 1479 1480 } // namespace traits 1481 1482 namespace execution { 1483 1484 template <> 1485 struct is_executor<io_context> : false_type 1486 { 1487 }; 1488 1489 } // namespace execution 1490 1491 #endif // !defined(GENERATING_DOCUMENTATION) 1492 1493 } // namespace asio 1494 } // namespace boost 1495 1496 #include <boost/asio/detail/pop_options.hpp> 1497 1498 #include <boost/asio/impl/io_context.hpp> 1499 #if defined(BOOST_ASIO_HEADER_ONLY) 1500 # include <boost/asio/impl/io_context.ipp> 1501 #endif // defined(BOOST_ASIO_HEADER_ONLY) 1502 1503 // If both io_context.hpp and strand.hpp have been included, automatically 1504 // include the header file needed for the io_context::strand class. 1505 #if !defined(BOOST_ASIO_NO_EXTENSIONS) 1506 # if defined(BOOST_ASIO_STRAND_HPP) 1507 # include <boost/asio/io_context_strand.hpp> 1508 # endif // defined(BOOST_ASIO_STRAND_HPP) 1509 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) 1510 1511 #endif // BOOST_ASIO_IO_CONTEXT_HPP
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |