io_context.hpp 50 KB

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