basic_descriptor.hpp 24 KB

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