basic_descriptor.hpp 23 KB

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