io_context.hpp 55 KB

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