io_context.hpp 55 KB

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