descriptor.hpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  1. //
  2. // posix/descriptor.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2018 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_POSIX_DESCRIPTOR_HPP
  11. #define BOOST_ASIO_POSIX_DESCRIPTOR_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
  17. #if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
  18. || defined(GENERATING_DOCUMENTATION)
  19. #include <boost/asio/async_result.hpp>
  20. #include <boost/asio/basic_io_object.hpp>
  21. #include <boost/asio/detail/handler_type_requirements.hpp>
  22. #include <boost/asio/detail/reactive_descriptor_service.hpp>
  23. #include <boost/asio/detail/throw_error.hpp>
  24. #include <boost/asio/error.hpp>
  25. #include <boost/asio/io_context.hpp>
  26. #include <boost/asio/posix/descriptor_base.hpp>
  27. #if defined(BOOST_ASIO_HAS_MOVE)
  28. # include <utility>
  29. #endif // defined(BOOST_ASIO_HAS_MOVE)
  30. #define BOOST_ASIO_SVC_T boost::asio::detail::reactive_descriptor_service
  31. #include <boost/asio/detail/push_options.hpp>
  32. namespace boost {
  33. namespace asio {
  34. namespace posix {
  35. /// Provides POSIX descriptor functionality.
  36. /**
  37. * The posix::descriptor class template provides the ability to wrap a
  38. * POSIX descriptor.
  39. *
  40. * @par Thread Safety
  41. * @e Distinct @e objects: Safe.@n
  42. * @e Shared @e objects: Unsafe.
  43. */
  44. class descriptor
  45. : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T>,
  46. public descriptor_base
  47. {
  48. public:
  49. /// The type of the executor associated with the object.
  50. typedef io_context::executor_type executor_type;
  51. /// The native representation of a descriptor.
  52. #if defined(GENERATING_DOCUMENTATION)
  53. typedef implementation_defined native_handle_type;
  54. #else
  55. typedef BOOST_ASIO_SVC_T::native_handle_type native_handle_type;
  56. #endif
  57. /// A descriptor is always the lowest layer.
  58. typedef descriptor lowest_layer_type;
  59. /// Construct a descriptor without opening it.
  60. /**
  61. * This constructor creates a descriptor without opening it.
  62. *
  63. * @param io_context The io_context object that the descriptor will use to
  64. * dispatch handlers for any asynchronous operations performed on the
  65. * descriptor.
  66. */
  67. explicit descriptor(boost::asio::io_context& io_context)
  68. : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
  69. {
  70. }
  71. /// Construct a descriptor on an existing native descriptor.
  72. /**
  73. * This constructor creates a descriptor object to hold an existing native
  74. * descriptor.
  75. *
  76. * @param io_context The io_context object that the descriptor will use to
  77. * dispatch handlers for any asynchronous operations performed on the
  78. * descriptor.
  79. *
  80. * @param native_descriptor A native descriptor.
  81. *
  82. * @throws boost::system::system_error Thrown on failure.
  83. */
  84. descriptor(boost::asio::io_context& io_context,
  85. const native_handle_type& native_descriptor)
  86. : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
  87. {
  88. boost::system::error_code ec;
  89. this->get_service().assign(this->get_implementation(),
  90. native_descriptor, ec);
  91. boost::asio::detail::throw_error(ec, "assign");
  92. }
  93. #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  94. /// Move-construct a descriptor from another.
  95. /**
  96. * This constructor moves a descriptor from one object to another.
  97. *
  98. * @param other The other descriptor object from which the move will
  99. * occur.
  100. *
  101. * @note Following the move, the moved-from object is in the same state as if
  102. * constructed using the @c descriptor(io_context&) constructor.
  103. */
  104. descriptor(descriptor&& other)
  105. : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other))
  106. {
  107. }
  108. /// Move-assign a descriptor from another.
  109. /**
  110. * This assignment operator moves a descriptor from one object to another.
  111. *
  112. * @param other The other descriptor object from which the move will
  113. * occur.
  114. *
  115. * @note Following the move, the moved-from object is in the same state as if
  116. * constructed using the @c descriptor(io_context&) constructor.
  117. */
  118. descriptor& operator=(descriptor&& other)
  119. {
  120. basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other));
  121. return *this;
  122. }
  123. #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  124. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  125. /// (Deprecated: Use get_executor().) Get the io_context associated with the
  126. /// object.
  127. /**
  128. * This function may be used to obtain the io_context object that the I/O
  129. * object uses to dispatch handlers for asynchronous operations.
  130. *
  131. * @return A reference to the io_context object that the I/O object will use
  132. * to dispatch handlers. Ownership is not transferred to the caller.
  133. */
  134. boost::asio::io_context& get_io_context()
  135. {
  136. return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context();
  137. }
  138. /// (Deprecated: Use get_executor().) Get the io_context associated with the
  139. /// object.
  140. /**
  141. * This function may be used to obtain the io_context object that the I/O
  142. * object uses to dispatch handlers for asynchronous operations.
  143. *
  144. * @return A reference to the io_context object that the I/O object will use
  145. * to dispatch handlers. Ownership is not transferred to the caller.
  146. */
  147. boost::asio::io_context& get_io_service()
  148. {
  149. return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service();
  150. }
  151. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  152. /// Get the executor associated with the object.
  153. executor_type get_executor() BOOST_ASIO_NOEXCEPT
  154. {
  155. return basic_io_object<BOOST_ASIO_SVC_T>::get_executor();
  156. }
  157. /// Get a reference to the lowest layer.
  158. /**
  159. * This function returns a reference to the lowest layer in a stack of
  160. * layers. Since a descriptor cannot contain any further layers, it
  161. * simply returns a reference to itself.
  162. *
  163. * @return A reference to the lowest layer in the stack of layers. Ownership
  164. * is not transferred to the caller.
  165. */
  166. lowest_layer_type& lowest_layer()
  167. {
  168. return *this;
  169. }
  170. /// Get a const reference to the lowest layer.
  171. /**
  172. * This function returns a const reference to the lowest layer in a stack of
  173. * layers. Since a descriptor cannot contain any further layers, it
  174. * simply returns a reference to itself.
  175. *
  176. * @return A const reference to the lowest layer in the stack of layers.
  177. * Ownership is not transferred to the caller.
  178. */
  179. const lowest_layer_type& lowest_layer() const
  180. {
  181. return *this;
  182. }
  183. /// Assign an existing native descriptor to the descriptor.
  184. /*
  185. * This function opens the descriptor to hold an existing native descriptor.
  186. *
  187. * @param native_descriptor A native descriptor.
  188. *
  189. * @throws boost::system::system_error Thrown on failure.
  190. */
  191. void assign(const native_handle_type& native_descriptor)
  192. {
  193. boost::system::error_code ec;
  194. this->get_service().assign(this->get_implementation(),
  195. native_descriptor, ec);
  196. boost::asio::detail::throw_error(ec, "assign");
  197. }
  198. /// Assign an existing native descriptor to the descriptor.
  199. /*
  200. * This function opens the descriptor to hold an existing native descriptor.
  201. *
  202. * @param native_descriptor A native descriptor.
  203. *
  204. * @param ec Set to indicate what error occurred, if any.
  205. */
  206. BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& native_descriptor,
  207. boost::system::error_code& ec)
  208. {
  209. this->get_service().assign(
  210. this->get_implementation(), native_descriptor, ec);
  211. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  212. }
  213. /// Determine whether the descriptor is open.
  214. bool is_open() const
  215. {
  216. return this->get_service().is_open(this->get_implementation());
  217. }
  218. /// Close the descriptor.
  219. /**
  220. * This function is used to close the descriptor. Any asynchronous read or
  221. * write operations will be cancelled immediately, and will complete with the
  222. * boost::asio::error::operation_aborted error.
  223. *
  224. * @throws boost::system::system_error Thrown on failure. Note that, even if
  225. * the function indicates an error, the underlying descriptor is closed.
  226. */
  227. void close()
  228. {
  229. boost::system::error_code ec;
  230. this->get_service().close(this->get_implementation(), ec);
  231. boost::asio::detail::throw_error(ec, "close");
  232. }
  233. /// Close the descriptor.
  234. /**
  235. * This function is used to close the descriptor. Any asynchronous read or
  236. * write operations will be cancelled immediately, and will complete with the
  237. * boost::asio::error::operation_aborted error.
  238. *
  239. * @param ec Set to indicate what error occurred, if any. Note that, even if
  240. * the function indicates an error, the underlying descriptor is closed.
  241. */
  242. BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
  243. {
  244. this->get_service().close(this->get_implementation(), ec);
  245. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  246. }
  247. /// Get the native descriptor representation.
  248. /**
  249. * This function may be used to obtain the underlying representation of the
  250. * descriptor. This is intended to allow access to native descriptor
  251. * functionality that is not otherwise provided.
  252. */
  253. native_handle_type native_handle()
  254. {
  255. return this->get_service().native_handle(this->get_implementation());
  256. }
  257. /// Release ownership of the native descriptor implementation.
  258. /**
  259. * This function may be used to obtain the underlying representation of the
  260. * descriptor. After calling this function, @c is_open() returns false. The
  261. * caller is responsible for closing the descriptor.
  262. *
  263. * All outstanding asynchronous read or write operations will finish
  264. * immediately, and the handlers for cancelled operations will be passed the
  265. * boost::asio::error::operation_aborted error.
  266. */
  267. native_handle_type release()
  268. {
  269. return this->get_service().release(this->get_implementation());
  270. }
  271. /// Cancel all asynchronous operations associated with the descriptor.
  272. /**
  273. * This function causes all outstanding asynchronous read or write operations
  274. * to finish immediately, and the handlers for cancelled operations will be
  275. * passed the boost::asio::error::operation_aborted error.
  276. *
  277. * @throws boost::system::system_error Thrown on failure.
  278. */
  279. void cancel()
  280. {
  281. boost::system::error_code ec;
  282. this->get_service().cancel(this->get_implementation(), ec);
  283. boost::asio::detail::throw_error(ec, "cancel");
  284. }
  285. /// Cancel all asynchronous operations associated with the descriptor.
  286. /**
  287. * This function causes all outstanding asynchronous read or write operations
  288. * to finish immediately, and the handlers for cancelled operations will be
  289. * passed the boost::asio::error::operation_aborted error.
  290. *
  291. * @param ec Set to indicate what error occurred, if any.
  292. */
  293. BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
  294. {
  295. this->get_service().cancel(this->get_implementation(), ec);
  296. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  297. }
  298. /// Perform an IO control command on the descriptor.
  299. /**
  300. * This function is used to execute an IO control command on the descriptor.
  301. *
  302. * @param command The IO control command to be performed on the descriptor.
  303. *
  304. * @throws boost::system::system_error Thrown on failure.
  305. *
  306. * @sa IoControlCommand @n
  307. * boost::asio::posix::descriptor_base::bytes_readable @n
  308. * boost::asio::posix::descriptor_base::non_blocking_io
  309. *
  310. * @par Example
  311. * Getting the number of bytes ready to read:
  312. * @code
  313. * boost::asio::posix::stream_descriptor descriptor(io_context);
  314. * ...
  315. * boost::asio::posix::stream_descriptor::bytes_readable command;
  316. * descriptor.io_control(command);
  317. * std::size_t bytes_readable = command.get();
  318. * @endcode
  319. */
  320. template <typename IoControlCommand>
  321. void io_control(IoControlCommand& command)
  322. {
  323. boost::system::error_code ec;
  324. this->get_service().io_control(this->get_implementation(), command, ec);
  325. boost::asio::detail::throw_error(ec, "io_control");
  326. }
  327. /// Perform an IO control command on the descriptor.
  328. /**
  329. * This function is used to execute an IO control command on the descriptor.
  330. *
  331. * @param command The IO control command to be performed on the descriptor.
  332. *
  333. * @param ec Set to indicate what error occurred, if any.
  334. *
  335. * @sa IoControlCommand @n
  336. * boost::asio::posix::descriptor_base::bytes_readable @n
  337. * boost::asio::posix::descriptor_base::non_blocking_io
  338. *
  339. * @par Example
  340. * Getting the number of bytes ready to read:
  341. * @code
  342. * boost::asio::posix::stream_descriptor descriptor(io_context);
  343. * ...
  344. * boost::asio::posix::stream_descriptor::bytes_readable command;
  345. * boost::system::error_code ec;
  346. * descriptor.io_control(command, ec);
  347. * if (ec)
  348. * {
  349. * // An error occurred.
  350. * }
  351. * std::size_t bytes_readable = command.get();
  352. * @endcode
  353. */
  354. template <typename IoControlCommand>
  355. BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command,
  356. boost::system::error_code& ec)
  357. {
  358. this->get_service().io_control(this->get_implementation(), command, ec);
  359. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  360. }
  361. /// Gets the non-blocking mode of the descriptor.
  362. /**
  363. * @returns @c true if the descriptor's synchronous operations will fail with
  364. * boost::asio::error::would_block if they are unable to perform the requested
  365. * operation immediately. If @c false, synchronous operations will block
  366. * until complete.
  367. *
  368. * @note The non-blocking mode has no effect on the behaviour of asynchronous
  369. * operations. Asynchronous operations will never fail with the error
  370. * boost::asio::error::would_block.
  371. */
  372. bool non_blocking() const
  373. {
  374. return this->get_service().non_blocking(this->get_implementation());
  375. }
  376. /// Sets the non-blocking mode of the descriptor.
  377. /**
  378. * @param mode If @c true, the descriptor's synchronous operations will fail
  379. * with boost::asio::error::would_block if they are unable to perform the
  380. * requested operation immediately. If @c false, synchronous operations will
  381. * block until complete.
  382. *
  383. * @throws boost::system::system_error Thrown on failure.
  384. *
  385. * @note The non-blocking mode has no effect on the behaviour of asynchronous
  386. * operations. Asynchronous operations will never fail with the error
  387. * boost::asio::error::would_block.
  388. */
  389. void non_blocking(bool mode)
  390. {
  391. boost::system::error_code ec;
  392. this->get_service().non_blocking(this->get_implementation(), mode, ec);
  393. boost::asio::detail::throw_error(ec, "non_blocking");
  394. }
  395. /// Sets the non-blocking mode of the descriptor.
  396. /**
  397. * @param mode If @c true, the descriptor's synchronous operations will fail
  398. * with boost::asio::error::would_block if they are unable to perform the
  399. * requested operation immediately. If @c false, synchronous operations will
  400. * block until complete.
  401. *
  402. * @param ec Set to indicate what error occurred, if any.
  403. *
  404. * @note The non-blocking mode has no effect on the behaviour of asynchronous
  405. * operations. Asynchronous operations will never fail with the error
  406. * boost::asio::error::would_block.
  407. */
  408. BOOST_ASIO_SYNC_OP_VOID non_blocking(
  409. bool mode, boost::system::error_code& ec)
  410. {
  411. this->get_service().non_blocking(this->get_implementation(), mode, ec);
  412. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  413. }
  414. /// Gets the non-blocking mode of the native descriptor implementation.
  415. /**
  416. * This function is used to retrieve the non-blocking mode of the underlying
  417. * native descriptor. This mode has no effect on the behaviour of the
  418. * descriptor object's synchronous operations.
  419. *
  420. * @returns @c true if the underlying descriptor is in non-blocking mode and
  421. * direct system calls may fail with boost::asio::error::would_block (or the
  422. * equivalent system error).
  423. *
  424. * @note The current non-blocking mode is cached by the descriptor object.
  425. * Consequently, the return value may be incorrect if the non-blocking mode
  426. * was set directly on the native descriptor.
  427. */
  428. bool native_non_blocking() const
  429. {
  430. return this->get_service().native_non_blocking(
  431. this->get_implementation());
  432. }
  433. /// Sets the non-blocking mode of the native descriptor implementation.
  434. /**
  435. * This function is used to modify the non-blocking mode of the underlying
  436. * native descriptor. It has no effect on the behaviour of the descriptor
  437. * object's synchronous operations.
  438. *
  439. * @param mode If @c true, the underlying descriptor is put into non-blocking
  440. * mode and direct system calls may fail with boost::asio::error::would_block
  441. * (or the equivalent system error).
  442. *
  443. * @throws boost::system::system_error Thrown on failure. If the @c mode is
  444. * @c false, but the current value of @c non_blocking() is @c true, this
  445. * function fails with boost::asio::error::invalid_argument, as the
  446. * combination does not make sense.
  447. */
  448. void native_non_blocking(bool mode)
  449. {
  450. boost::system::error_code ec;
  451. this->get_service().native_non_blocking(
  452. this->get_implementation(), mode, ec);
  453. boost::asio::detail::throw_error(ec, "native_non_blocking");
  454. }
  455. /// Sets the non-blocking mode of the native descriptor implementation.
  456. /**
  457. * This function is used to modify the non-blocking mode of the underlying
  458. * native descriptor. It has no effect on the behaviour of the descriptor
  459. * object's synchronous operations.
  460. *
  461. * @param mode If @c true, the underlying descriptor is put into non-blocking
  462. * mode and direct system calls may fail with boost::asio::error::would_block
  463. * (or the equivalent system error).
  464. *
  465. * @param ec Set to indicate what error occurred, if any. If the @c mode is
  466. * @c false, but the current value of @c non_blocking() is @c true, this
  467. * function fails with boost::asio::error::invalid_argument, as the
  468. * combination does not make sense.
  469. */
  470. BOOST_ASIO_SYNC_OP_VOID native_non_blocking(
  471. bool mode, boost::system::error_code& ec)
  472. {
  473. this->get_service().native_non_blocking(
  474. this->get_implementation(), mode, ec);
  475. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  476. }
  477. /// Wait for the descriptor to become ready to read, ready to write, or to
  478. /// have pending error conditions.
  479. /**
  480. * This function is used to perform a blocking wait for a descriptor to enter
  481. * a ready to read, write or error condition state.
  482. *
  483. * @param w Specifies the desired descriptor state.
  484. *
  485. * @par Example
  486. * Waiting for a descriptor to become readable.
  487. * @code
  488. * boost::asio::posix::stream_descriptor descriptor(io_context);
  489. * ...
  490. * descriptor.wait(boost::asio::posix::stream_descriptor::wait_read);
  491. * @endcode
  492. */
  493. void wait(wait_type w)
  494. {
  495. boost::system::error_code ec;
  496. this->get_service().wait(this->get_implementation(), w, ec);
  497. boost::asio::detail::throw_error(ec, "wait");
  498. }
  499. /// Wait for the descriptor to become ready to read, ready to write, or to
  500. /// have pending error conditions.
  501. /**
  502. * This function is used to perform a blocking wait for a descriptor to enter
  503. * a ready to read, write or error condition state.
  504. *
  505. * @param w Specifies the desired descriptor state.
  506. *
  507. * @param ec Set to indicate what error occurred, if any.
  508. *
  509. * @par Example
  510. * Waiting for a descriptor to become readable.
  511. * @code
  512. * boost::asio::posix::stream_descriptor descriptor(io_context);
  513. * ...
  514. * boost::system::error_code ec;
  515. * descriptor.wait(boost::asio::posix::stream_descriptor::wait_read, ec);
  516. * @endcode
  517. */
  518. BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec)
  519. {
  520. this->get_service().wait(this->get_implementation(), w, ec);
  521. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  522. }
  523. /// Asynchronously wait for the descriptor to become ready to read, ready to
  524. /// write, or to have pending error conditions.
  525. /**
  526. * This function is used to perform an asynchronous wait for a descriptor to
  527. * enter a ready to read, write or error condition state.
  528. *
  529. * @param w Specifies the desired descriptor state.
  530. *
  531. * @param handler The handler to be called when the wait operation completes.
  532. * Copies will be made of the handler as required. The function signature of
  533. * the handler must be:
  534. * @code void handler(
  535. * const boost::system::error_code& error // Result of operation
  536. * ); @endcode
  537. * Regardless of whether the asynchronous operation completes immediately or
  538. * not, the handler will not be invoked from within this function. Invocation
  539. * of the handler will be performed in a manner equivalent to using
  540. * boost::asio::io_context::post().
  541. *
  542. * @par Example
  543. * @code
  544. * void wait_handler(const boost::system::error_code& error)
  545. * {
  546. * if (!error)
  547. * {
  548. * // Wait succeeded.
  549. * }
  550. * }
  551. *
  552. * ...
  553. *
  554. * boost::asio::posix::stream_descriptor descriptor(io_context);
  555. * ...
  556. * descriptor.async_wait(
  557. * boost::asio::posix::stream_descriptor::wait_read,
  558. * wait_handler);
  559. * @endcode
  560. */
  561. template <typename WaitHandler>
  562. BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
  563. void (boost::system::error_code))
  564. async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
  565. {
  566. // If you get an error on the following line it means that your handler does
  567. // not meet the documented type requirements for a WaitHandler.
  568. BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
  569. async_completion<WaitHandler,
  570. void (boost::system::error_code)> init(handler);
  571. this->get_service().async_wait(
  572. this->get_implementation(), w, init.completion_handler);
  573. return init.result.get();
  574. }
  575. protected:
  576. /// Protected destructor to prevent deletion through this type.
  577. /**
  578. * This function destroys the descriptor, cancelling any outstanding
  579. * asynchronous wait operations associated with the descriptor as if by
  580. * calling @c cancel.
  581. */
  582. ~descriptor()
  583. {
  584. }
  585. };
  586. } // namespace posix
  587. } // namespace asio
  588. } // namespace boost
  589. #include <boost/asio/detail/pop_options.hpp>
  590. #undef BOOST_ASIO_SVC_T
  591. #endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
  592. // || defined(GENERATING_DOCUMENTATION)
  593. #endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
  594. #endif // BOOST_ASIO_POSIX_DESCRIPTOR_HPP