io_service.hpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  1. //
  2. // io_service.hpp
  3. // ~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2008 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_SERVICE_HPP
  11. #define BOOST_ASIO_IO_SERVICE_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/push_options.hpp>
  16. #include <boost/asio/detail/push_options.hpp>
  17. #include <cstddef>
  18. #include <stdexcept>
  19. #include <typeinfo>
  20. #include <boost/config.hpp>
  21. #include <boost/throw_exception.hpp>
  22. #include <boost/system/error_code.hpp>
  23. #include <boost/asio/detail/pop_options.hpp>
  24. #include <boost/asio/detail/dev_poll_reactor_fwd.hpp>
  25. #include <boost/asio/detail/epoll_reactor_fwd.hpp>
  26. #include <boost/asio/detail/kqueue_reactor_fwd.hpp>
  27. #include <boost/asio/detail/noncopyable.hpp>
  28. #include <boost/asio/detail/select_reactor_fwd.hpp>
  29. #include <boost/asio/detail/service_registry_fwd.hpp>
  30. #include <boost/asio/detail/signal_init.hpp>
  31. #include <boost/asio/detail/task_io_service_fwd.hpp>
  32. #include <boost/asio/detail/win_iocp_io_service_fwd.hpp>
  33. #include <boost/asio/detail/winsock_init.hpp>
  34. #include <boost/asio/detail/wrapped_handler.hpp>
  35. namespace boost {
  36. namespace asio {
  37. class io_service;
  38. template <typename Service> Service& use_service(io_service& ios);
  39. template <typename Service> void add_service(io_service& ios, Service* svc);
  40. template <typename Service> bool has_service(io_service& ios);
  41. /// Provides core I/O functionality.
  42. /**
  43. * The io_service class provides the core I/O functionality for users of the
  44. * asynchronous I/O objects, including:
  45. *
  46. * @li boost::asio::ip::tcp::socket
  47. * @li boost::asio::ip::tcp::acceptor
  48. * @li boost::asio::ip::udp::socket
  49. * @li boost::asio::deadline_timer.
  50. *
  51. * The io_service class also includes facilities intended for developers of
  52. * custom asynchronous services.
  53. *
  54. * @par Thread Safety
  55. * @e Distinct @e objects: Safe.@n
  56. * @e Shared @e objects: Safe, with the exception that calling reset() while
  57. * there are unfinished run(), run_one(), poll() or poll_one() calls results in
  58. * undefined behaviour.
  59. *
  60. * @par Concepts:
  61. * Dispatcher.
  62. *
  63. * @par Synchronous and asynchronous operations
  64. *
  65. * Synchronous operations on I/O objects implicitly run the io_service object
  66. * for an individual operation. The io_service functions run(), run_one(),
  67. * poll() or poll_one() must be called for the io_service to perform
  68. * asynchronous operations on behalf of a C++ program. Notification that an
  69. * asynchronous operation has completed is delivered by invocation of the
  70. * associated handler. Handlers are invoked only by a thread that is currently
  71. * calling any overload of run(), run_one(), poll() or poll_one() for the
  72. * io_service.
  73. *
  74. * @par Effect of exceptions thrown from handlers
  75. *
  76. * If an exception is thrown from a handler, the exception is allowed to
  77. * propagate through the throwing thread's invocation of run(), run_one(),
  78. * poll() or poll_one(). No other threads that are calling any of these
  79. * functions are affected. It is then the responsibility of the application to
  80. * catch the exception.
  81. *
  82. * After the exception has been caught, the run(), run_one(), poll() or
  83. * poll_one() call may be restarted @em without the need for an intervening
  84. * call to reset(). This allows the thread to rejoin the io_service object's
  85. * thread pool without impacting any other threads in the pool.
  86. *
  87. * For example:
  88. *
  89. * @code
  90. * boost::asio::io_service io_service;
  91. * ...
  92. * for (;;)
  93. * {
  94. * try
  95. * {
  96. * io_service.run();
  97. * break; // run() exited normally
  98. * }
  99. * catch (my_exception& e)
  100. * {
  101. * // Deal with exception as appropriate.
  102. * }
  103. * }
  104. * @endcode
  105. *
  106. * @par Stopping the io_service from running out of work
  107. *
  108. * Some applications may need to prevent an io_service object's run() call from
  109. * returning when there is no more work to do. For example, the io_service may
  110. * be being run in a background thread that is launched prior to the
  111. * application's asynchronous operations. The run() call may be kept running by
  112. * creating an object of type boost::asio::io_service::work:
  113. *
  114. * @code boost::asio::io_service io_service;
  115. * boost::asio::io_service::work work(io_service);
  116. * ... @endcode
  117. *
  118. * To effect a shutdown, the application will then need to call the io_service
  119. * object's stop() member function. This will cause the io_service run() call
  120. * to return as soon as possible, abandoning unfinished operations and without
  121. * permitting ready handlers to be dispatched.
  122. *
  123. * Alternatively, if the application requires that all operations and handlers
  124. * be allowed to finish normally, the work object may be explicitly destroyed.
  125. *
  126. * @code boost::asio::io_service io_service;
  127. * auto_ptr<boost::asio::io_service::work> work(
  128. * new boost::asio::io_service::work(io_service));
  129. * ...
  130. * work.reset(); // Allow run() to exit. @endcode
  131. *
  132. * @par The io_service class and I/O services
  133. *
  134. * Class io_service implements an extensible, type-safe, polymorphic set of I/O
  135. * services, indexed by service type. An object of class io_service must be
  136. * initialised before I/O objects such as sockets, resolvers and timers can be
  137. * used. These I/O objects are distinguished by having constructors that accept
  138. * an @c io_service& parameter.
  139. *
  140. * I/O services exist to manage the logical interface to the operating system on
  141. * behalf of the I/O objects. In particular, there are resources that are shared
  142. * across a class of I/O objects. For example, timers may be implemented in
  143. * terms of a single timer queue. The I/O services manage these shared
  144. * resources.
  145. *
  146. * Access to the services of an io_service is via three function templates,
  147. * use_service(), add_service() and has_service().
  148. *
  149. * In a call to @c use_service<Service>(), the type argument chooses a service,
  150. * making available all members of the named type. If @c Service is not present
  151. * in an io_service, an object of type @c Service is created and added to the
  152. * io_service. A C++ program can check if an io_service implements a
  153. * particular service with the function template @c has_service<Service>().
  154. *
  155. * Service objects may be explicitly added to an io_service using the function
  156. * template @c add_service<Service>(). If the @c Service is already present, the
  157. * service_already_exists exception is thrown. If the owner of the service is
  158. * not the same object as the io_service parameter, the invalid_service_owner
  159. * exception is thrown.
  160. *
  161. * Once a service reference is obtained from an io_service object by calling
  162. * use_service(), that reference remains usable as long as the owning io_service
  163. * object exists.
  164. *
  165. * All I/O service implementations have io_service::service as a public base
  166. * class. Custom I/O services may be implemented by deriving from this class and
  167. * then added to an io_service using the facilities described above.
  168. */
  169. class io_service
  170. : private noncopyable
  171. {
  172. private:
  173. // The type of the platform-specific implementation.
  174. #if defined(BOOST_ASIO_HAS_IOCP)
  175. typedef detail::win_iocp_io_service impl_type;
  176. friend class detail::win_iocp_overlapped_ptr;
  177. #elif defined(BOOST_ASIO_HAS_EPOLL)
  178. typedef detail::task_io_service<detail::epoll_reactor<false> > impl_type;
  179. #elif defined(BOOST_ASIO_HAS_KQUEUE)
  180. typedef detail::task_io_service<detail::kqueue_reactor<false> > impl_type;
  181. #elif defined(BOOST_ASIO_HAS_DEV_POLL)
  182. typedef detail::task_io_service<detail::dev_poll_reactor<false> > impl_type;
  183. #else
  184. typedef detail::task_io_service<detail::select_reactor<false> > impl_type;
  185. #endif
  186. public:
  187. class work;
  188. friend class work;
  189. class id;
  190. class service;
  191. class strand;
  192. /// Constructor.
  193. io_service();
  194. /// Constructor.
  195. /**
  196. * Construct with a hint about the required level of concurrency.
  197. *
  198. * @param concurrency_hint A suggestion to the implementation on how many
  199. * threads it should allow to run simultaneously.
  200. */
  201. explicit io_service(std::size_t concurrency_hint);
  202. /// Destructor.
  203. /**
  204. * On destruction, the io_service performs the following sequence of
  205. * operations:
  206. *
  207. * @li For each service object @c svc in the io_service set, in reverse order
  208. * of the beginning of service object lifetime, performs
  209. * @c svc->shutdown_service().
  210. *
  211. * @li Uninvoked handler objects that were scheduled for deferred invocation
  212. * on the io_service, or any associated strand, are destroyed.
  213. *
  214. * @li For each service object @c svc in the io_service set, in reverse order
  215. * of the beginning of service object lifetime, performs
  216. * <tt>delete static_cast<io_service::service*>(svc)</tt>.
  217. *
  218. * @note The destruction sequence described above permits programs to
  219. * simplify their resource management by using @c shared_ptr<>. Where an
  220. * object's lifetime is tied to the lifetime of a connection (or some other
  221. * sequence of asynchronous operations), a @c shared_ptr to the object would
  222. * be bound into the handlers for all asynchronous operations associated with
  223. * it. This works as follows:
  224. *
  225. * @li When a single connection ends, all associated asynchronous operations
  226. * complete. The corresponding handler objects are destroyed, and all
  227. * @c shared_ptr references to the objects are destroyed.
  228. *
  229. * @li To shut down the whole program, the io_service function stop() is
  230. * called to terminate any run() calls as soon as possible. The io_service
  231. * destructor defined above destroys all handlers, causing all @c shared_ptr
  232. * references to all connection objects to be destroyed.
  233. */
  234. ~io_service();
  235. /// Run the io_service object's event processing loop.
  236. /**
  237. * The run() function blocks until all work has finished and there are no
  238. * more handlers to be dispatched, or until the io_service has been stopped.
  239. *
  240. * Multiple threads may call the run() function to set up a pool of threads
  241. * from which the io_service may execute handlers. All threads that are
  242. * waiting in the pool are equivalent and the io_service may choose any one
  243. * of them to invoke a handler.
  244. *
  245. * The run() function may be safely called again once it has completed only
  246. * after a call to reset().
  247. *
  248. * @return The number of handlers that were executed.
  249. *
  250. * @throws boost::system::system_error Thrown on failure.
  251. *
  252. * @note The run() function must not be called from a thread that is currently
  253. * calling one of run(), run_one(), poll() or poll_one() on the same
  254. * io_service object.
  255. *
  256. * The poll() function may also be used to dispatch ready handlers, but
  257. * without blocking.
  258. */
  259. std::size_t run();
  260. /// Run the io_service object's event processing loop.
  261. /**
  262. * The run() function blocks until all work has finished and there are no
  263. * more handlers to be dispatched, or until the io_service has been stopped.
  264. *
  265. * Multiple threads may call the run() function to set up a pool of threads
  266. * from which the io_service may execute handlers. All threads that are
  267. * waiting in the pool are equivalent and the io_service may choose any one
  268. * of them to invoke a handler.
  269. *
  270. * The run() function may be safely called again once it has completed only
  271. * after a call to reset().
  272. *
  273. * @param ec Set to indicate what error occurred, if any.
  274. *
  275. * @return The number of handlers that were executed.
  276. *
  277. * @note The run() function must not be called from a thread that is currently
  278. * calling one of run(), run_one(), poll() or poll_one() on the same
  279. * io_service object.
  280. *
  281. * The poll() function may also be used to dispatch ready handlers, but
  282. * without blocking.
  283. */
  284. std::size_t run(boost::system::error_code& ec);
  285. /// Run the io_service object's event processing loop to execute at most one
  286. /// handler.
  287. /**
  288. * The run_one() function blocks until one handler has been dispatched, or
  289. * until the io_service has been stopped.
  290. *
  291. * @return The number of handlers that were executed.
  292. *
  293. * @throws boost::system::system_error Thrown on failure.
  294. */
  295. std::size_t run_one();
  296. /// Run the io_service object's event processing loop to execute at most one
  297. /// handler.
  298. /**
  299. * The run_one() function blocks until one handler has been dispatched, or
  300. * until the io_service has been stopped.
  301. *
  302. * @param ec Set to indicate what error occurred, if any.
  303. *
  304. * @return The number of handlers that were executed.
  305. */
  306. std::size_t run_one(boost::system::error_code& ec);
  307. /// Run the io_service object's event processing loop to execute ready
  308. /// handlers.
  309. /**
  310. * The poll() function runs handlers that are ready to run, without blocking,
  311. * until the io_service has been stopped or there are no more ready handlers.
  312. *
  313. * @return The number of handlers that were executed.
  314. *
  315. * @throws boost::system::system_error Thrown on failure.
  316. */
  317. std::size_t poll();
  318. /// Run the io_service object's event processing loop to execute ready
  319. /// handlers.
  320. /**
  321. * The poll() function runs handlers that are ready to run, without blocking,
  322. * until the io_service has been stopped or there are no more ready handlers.
  323. *
  324. * @param ec Set to indicate what error occurred, if any.
  325. *
  326. * @return The number of handlers that were executed.
  327. */
  328. std::size_t poll(boost::system::error_code& ec);
  329. /// Run the io_service object's event processing loop to execute one ready
  330. /// handler.
  331. /**
  332. * The poll_one() function runs at most one handler that is ready to run,
  333. * without blocking.
  334. *
  335. * @return The number of handlers that were executed.
  336. *
  337. * @throws boost::system::system_error Thrown on failure.
  338. */
  339. std::size_t poll_one();
  340. /// Run the io_service object's event processing loop to execute one ready
  341. /// handler.
  342. /**
  343. * The poll_one() function runs at most one handler that is ready to run,
  344. * without blocking.
  345. *
  346. * @param ec Set to indicate what error occurred, if any.
  347. *
  348. * @return The number of handlers that were executed.
  349. */
  350. std::size_t poll_one(boost::system::error_code& ec);
  351. /// Stop the io_service object's event processing loop.
  352. /**
  353. * This function does not block, but instead simply signals the io_service to
  354. * stop. All invocations of its run() or run_one() member functions should
  355. * return as soon as possible. Subsequent calls to run(), run_one(), poll()
  356. * or poll_one() will return immediately until reset() is called.
  357. */
  358. void stop();
  359. /// Reset the io_service in preparation for a subsequent run() invocation.
  360. /**
  361. * This function must be called prior to any second or later set of
  362. * invocations of the run(), run_one(), poll() or poll_one() functions when a
  363. * previous invocation of these functions returned due to the io_service
  364. * being stopped or running out of work. This function allows the io_service
  365. * to reset any internal state, such as a "stopped" flag.
  366. *
  367. * This function must not be called while there are any unfinished calls to
  368. * the run(), run_one(), poll() or poll_one() functions.
  369. */
  370. void reset();
  371. /// Request the io_service to invoke the given handler.
  372. /**
  373. * This function is used to ask the io_service to execute the given handler.
  374. *
  375. * The io_service guarantees that the handler will only be called in a thread
  376. * in which the run(), run_one(), poll() or poll_one() member functions is
  377. * currently being invoked. The handler may be executed inside this function
  378. * if the guarantee can be met.
  379. *
  380. * @param handler The handler to be called. The io_service will make
  381. * a copy of the handler object as required. The function signature of the
  382. * handler must be: @code void handler(); @endcode
  383. */
  384. template <typename CompletionHandler>
  385. void dispatch(CompletionHandler handler);
  386. /// Request the io_service to invoke the given handler and return immediately.
  387. /**
  388. * This function is used to ask the io_service to execute the given handler,
  389. * but without allowing the io_service to call the handler from inside this
  390. * function.
  391. *
  392. * The io_service guarantees that the handler will only be called in a thread
  393. * in which the run(), run_one(), poll() or poll_one() member functions is
  394. * currently being invoked.
  395. *
  396. * @param handler The handler to be called. The io_service will make
  397. * a copy of the handler object as required. The function signature of the
  398. * handler must be: @code void handler(); @endcode
  399. */
  400. template <typename CompletionHandler>
  401. void post(CompletionHandler handler);
  402. /// Create a new handler that automatically dispatches the wrapped handler
  403. /// on the io_service.
  404. /**
  405. * This function is used to create a new handler function object that, when
  406. * invoked, will automatically pass the wrapped handler to the io_service
  407. * object's dispatch function.
  408. *
  409. * @param handler The handler to be wrapped. The io_service will make a copy
  410. * of the handler object as required. The function signature of the handler
  411. * must be: @code void handler(A1 a1, ... An an); @endcode
  412. *
  413. * @return A function object that, when invoked, passes the wrapped handler to
  414. * the io_service object's dispatch function. Given a function object with the
  415. * signature:
  416. * @code R f(A1 a1, ... An an); @endcode
  417. * If this function object is passed to the wrap function like so:
  418. * @code io_service.wrap(f); @endcode
  419. * then the return value is a function object with the signature
  420. * @code void g(A1 a1, ... An an); @endcode
  421. * that, when invoked, executes code equivalent to:
  422. * @code io_service.dispatch(boost::bind(f, a1, ... an)); @endcode
  423. */
  424. template <typename Handler>
  425. #if defined(GENERATING_DOCUMENTATION)
  426. unspecified
  427. #else
  428. detail::wrapped_handler<io_service&, Handler>
  429. #endif
  430. wrap(Handler handler);
  431. /// Obtain the service object corresponding to the given type.
  432. /**
  433. * This function is used to locate a service object that corresponds to
  434. * the given service type. If there is no existing implementation of the
  435. * service, then the io_service will create a new instance of the service.
  436. *
  437. * @param ios The io_service object that owns the service.
  438. *
  439. * @return The service interface implementing the specified service type.
  440. * Ownership of the service interface is not transferred to the caller.
  441. */
  442. template <typename Service>
  443. friend Service& use_service(io_service& ios);
  444. /// Add a service object to the io_service.
  445. /**
  446. * This function is used to add a service to the io_service.
  447. *
  448. * @param ios The io_service object that owns the service.
  449. *
  450. * @param svc The service object. On success, ownership of the service object
  451. * is transferred to the io_service. When the io_service object is destroyed,
  452. * it will destroy the service object by performing:
  453. * @code delete static_cast<io_service::service*>(svc) @endcode
  454. *
  455. * @throws boost::asio::service_already_exists Thrown if a service of the
  456. * given type is already present in the io_service.
  457. *
  458. * @throws boost::asio::invalid_service_owner Thrown if the service's owning
  459. * io_service is not the io_service object specified by the ios parameter.
  460. */
  461. template <typename Service>
  462. friend void add_service(io_service& ios, Service* svc);
  463. /// Determine if an io_service contains a specified service type.
  464. /**
  465. * This function is used to determine whether the io_service contains a
  466. * service object corresponding to the given service type.
  467. *
  468. * @param ios The io_service object that owns the service.
  469. *
  470. * @return A boolean indicating whether the io_service contains the service.
  471. */
  472. template <typename Service>
  473. friend bool has_service(io_service& ios);
  474. private:
  475. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  476. detail::winsock_init<> init_;
  477. #elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \
  478. || defined(__osf__)
  479. detail::signal_init<> init_;
  480. #endif
  481. // The service registry.
  482. boost::asio::detail::service_registry* service_registry_;
  483. // The implementation.
  484. impl_type& impl_;
  485. };
  486. /// Class to inform the io_service when it has work to do.
  487. /**
  488. * The work class is used to inform the io_service when work starts and
  489. * finishes. This ensures that the io_service object's run() function will not
  490. * exit while work is underway, and that it does exit when there is no
  491. * unfinished work remaining.
  492. *
  493. * The work class is copy-constructible so that it may be used as a data member
  494. * in a handler class. It is not assignable.
  495. */
  496. class io_service::work
  497. {
  498. public:
  499. /// Constructor notifies the io_service that work is starting.
  500. /**
  501. * The constructor is used to inform the io_service that some work has begun.
  502. * This ensures that the io_service object's run() function will not exit
  503. * while the work is underway.
  504. */
  505. explicit work(boost::asio::io_service& io_service);
  506. /// Copy constructor notifies the io_service that work is starting.
  507. /**
  508. * The constructor is used to inform the io_service that some work has begun.
  509. * This ensures that the io_service object's run() function will not exit
  510. * while the work is underway.
  511. */
  512. work(const work& other);
  513. /// Destructor notifies the io_service that the work is complete.
  514. /**
  515. * The destructor is used to inform the io_service that some work has
  516. * finished. Once the count of unfinished work reaches zero, the io_service
  517. * object's run() function is permitted to exit.
  518. */
  519. ~work();
  520. /// (Deprecated: use get_io_service().) Get the io_service associated with the
  521. /// work.
  522. boost::asio::io_service& io_service();
  523. /// Get the io_service associated with the work.
  524. boost::asio::io_service& get_io_service();
  525. private:
  526. // Prevent assignment.
  527. void operator=(const work& other);
  528. // The io_service.
  529. boost::asio::io_service& io_service_;
  530. };
  531. /// Class used to uniquely identify a service.
  532. class io_service::id
  533. : private noncopyable
  534. {
  535. public:
  536. /// Constructor.
  537. id() {}
  538. };
  539. /// Base class for all io_service services.
  540. class io_service::service
  541. : private noncopyable
  542. {
  543. public:
  544. /// (Deprecated: use get_io_service().) Get the io_service object that owns
  545. /// the service.
  546. boost::asio::io_service& io_service();
  547. /// Get the io_service object that owns the service.
  548. boost::asio::io_service& get_io_service();
  549. protected:
  550. /// Constructor.
  551. /**
  552. * @param owner The io_service object that owns the service.
  553. */
  554. service(boost::asio::io_service& owner);
  555. /// Destructor.
  556. virtual ~service();
  557. private:
  558. /// Destroy all user-defined handler objects owned by the service.
  559. virtual void shutdown_service() = 0;
  560. friend class boost::asio::detail::service_registry;
  561. boost::asio::io_service& owner_;
  562. const std::type_info* type_info_;
  563. const boost::asio::io_service::id* id_;
  564. service* next_;
  565. };
  566. /// Exception thrown when trying to add a duplicate service to an io_service.
  567. class service_already_exists
  568. : public std::logic_error
  569. {
  570. public:
  571. service_already_exists()
  572. : std::logic_error("Service already exists.")
  573. {
  574. }
  575. };
  576. /// Exception thrown when trying to add a service object to an io_service where
  577. /// the service has a different owner.
  578. class invalid_service_owner
  579. : public std::logic_error
  580. {
  581. public:
  582. invalid_service_owner()
  583. : std::logic_error("Invalid service owner.")
  584. {
  585. }
  586. };
  587. } // namespace asio
  588. } // namespace boost
  589. #include <boost/asio/impl/io_service.ipp>
  590. #include <boost/asio/detail/pop_options.hpp>
  591. #endif // BOOST_ASIO_IO_SERVICE_HPP