io_context.hpp 53 KB

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