basic_readable_pipe.hpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. //
  2. // basic_readable_pipe.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_BASIC_READABLE_PIPE_HPP
  11. #define ASIO_BASIC_READABLE_PIPE_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_PIPE) \
  17. || defined(GENERATING_DOCUMENTATION)
  18. #include <string>
  19. #include "asio/any_io_executor.hpp"
  20. #include "asio/async_result.hpp"
  21. #include "asio/detail/handler_type_requirements.hpp"
  22. #include "asio/detail/io_object_impl.hpp"
  23. #include "asio/detail/non_const_lvalue.hpp"
  24. #include "asio/detail/throw_error.hpp"
  25. #include "asio/detail/type_traits.hpp"
  26. #include "asio/error.hpp"
  27. #include "asio/execution_context.hpp"
  28. #if defined(ASIO_HAS_IOCP)
  29. # include "asio/detail/win_iocp_handle_service.hpp"
  30. #elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)
  31. # include "asio/detail/io_uring_descriptor_service.hpp"
  32. #else
  33. # include "asio/detail/reactive_descriptor_service.hpp"
  34. #endif
  35. #if defined(ASIO_HAS_MOVE)
  36. # include <utility>
  37. #endif // defined(ASIO_HAS_MOVE)
  38. #include "asio/detail/push_options.hpp"
  39. namespace asio {
  40. /// Provides pipe functionality.
  41. /**
  42. * The basic_readable_pipe class provides a wrapper over pipe
  43. * functionality.
  44. *
  45. * @par Thread Safety
  46. * @e Distinct @e objects: Safe.@n
  47. * @e Shared @e objects: Unsafe.
  48. */
  49. template <typename Executor = any_io_executor>
  50. class basic_readable_pipe
  51. {
  52. public:
  53. /// The type of the executor associated with the object.
  54. typedef Executor executor_type;
  55. /// Rebinds the pipe type to another executor.
  56. template <typename Executor1>
  57. struct rebind_executor
  58. {
  59. /// The pipe type when rebound to the specified executor.
  60. typedef basic_readable_pipe<Executor1> other;
  61. };
  62. /// The native representation of a pipe.
  63. #if defined(GENERATING_DOCUMENTATION)
  64. typedef implementation_defined native_handle_type;
  65. #elif defined(ASIO_HAS_IOCP)
  66. typedef detail::win_iocp_handle_service::native_handle_type
  67. native_handle_type;
  68. #elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)
  69. typedef detail::io_uring_descriptor_service::native_handle_type
  70. native_handle_type;
  71. #else
  72. typedef detail::reactive_descriptor_service::native_handle_type
  73. native_handle_type;
  74. #endif
  75. /// A basic_readable_pipe is always the lowest layer.
  76. typedef basic_readable_pipe lowest_layer_type;
  77. /// Construct a basic_readable_pipe without opening it.
  78. /**
  79. * This constructor creates a pipe without opening it.
  80. *
  81. * @param ex The I/O executor that the pipe will use, by default, to dispatch
  82. * handlers for any asynchronous operations performed on the pipe.
  83. */
  84. explicit basic_readable_pipe(const executor_type& ex)
  85. : impl_(0, ex)
  86. {
  87. }
  88. /// Construct a basic_readable_pipe without opening it.
  89. /**
  90. * This constructor creates a pipe without opening it.
  91. *
  92. * @param context An execution context which provides the I/O executor that
  93. * the pipe will use, by default, to dispatch handlers for any asynchronous
  94. * operations performed on the pipe.
  95. */
  96. template <typename ExecutionContext>
  97. explicit basic_readable_pipe(ExecutionContext& context,
  98. typename constraint<
  99. is_convertible<ExecutionContext&, execution_context&>::value,
  100. defaulted_constraint
  101. >::type = defaulted_constraint())
  102. : impl_(0, 0, context)
  103. {
  104. }
  105. /// Construct a basic_readable_pipe on an existing native pipe.
  106. /**
  107. * This constructor creates a pipe object to hold an existing native
  108. * pipe.
  109. *
  110. * @param ex The I/O executor that the pipe will use, by default, to
  111. * dispatch handlers for any asynchronous operations performed on the
  112. * pipe.
  113. *
  114. * @param native_pipe A native pipe.
  115. *
  116. * @throws asio::system_error Thrown on failure.
  117. */
  118. basic_readable_pipe(const executor_type& ex,
  119. const native_handle_type& native_pipe)
  120. : impl_(0, ex)
  121. {
  122. asio::error_code ec;
  123. impl_.get_service().assign(impl_.get_implementation(),
  124. native_pipe, ec);
  125. asio::detail::throw_error(ec, "assign");
  126. }
  127. /// Construct a basic_readable_pipe on an existing native pipe.
  128. /**
  129. * This constructor creates a pipe object to hold an existing native
  130. * pipe.
  131. *
  132. * @param context An execution context which provides the I/O executor that
  133. * the pipe will use, by default, to dispatch handlers for any
  134. * asynchronous operations performed on the pipe.
  135. *
  136. * @param native_pipe A native pipe.
  137. *
  138. * @throws asio::system_error Thrown on failure.
  139. */
  140. template <typename ExecutionContext>
  141. basic_readable_pipe(ExecutionContext& context,
  142. const native_handle_type& native_pipe,
  143. typename constraint<
  144. is_convertible<ExecutionContext&, execution_context&>::value
  145. >::type = 0)
  146. : impl_(0, 0, context)
  147. {
  148. asio::error_code ec;
  149. impl_.get_service().assign(impl_.get_implementation(),
  150. native_pipe, ec);
  151. asio::detail::throw_error(ec, "assign");
  152. }
  153. #if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  154. /// Move-construct a basic_readable_pipe from another.
  155. /**
  156. * This constructor moves a pipe from one object to another.
  157. *
  158. * @param other The other basic_readable_pipe object from which the move will
  159. * occur.
  160. *
  161. * @note Following the move, the moved-from object is in the same state as if
  162. * constructed using the @c basic_readable_pipe(const executor_type&)
  163. * constructor.
  164. */
  165. basic_readable_pipe(basic_readable_pipe&& other)
  166. : impl_(std::move(other.impl_))
  167. {
  168. }
  169. /// Move-assign a basic_readable_pipe from another.
  170. /**
  171. * This assignment operator moves a pipe from one object to another.
  172. *
  173. * @param other The other basic_readable_pipe object from which the move will
  174. * occur.
  175. *
  176. * @note Following the move, the moved-from object is in the same state as if
  177. * constructed using the @c basic_readable_pipe(const executor_type&)
  178. * constructor.
  179. */
  180. basic_readable_pipe& operator=(basic_readable_pipe&& other)
  181. {
  182. impl_ = std::move(other.impl_);
  183. return *this;
  184. }
  185. #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  186. /// Destroys the pipe.
  187. /**
  188. * This function destroys the pipe, cancelling any outstanding
  189. * asynchronous wait operations associated with the pipe as if by
  190. * calling @c cancel.
  191. */
  192. ~basic_readable_pipe()
  193. {
  194. }
  195. /// Get the executor associated with the object.
  196. executor_type get_executor() ASIO_NOEXCEPT
  197. {
  198. return impl_.get_executor();
  199. }
  200. /// Get a reference to the lowest layer.
  201. /**
  202. * This function returns a reference to the lowest layer in a stack of
  203. * layers. Since a basic_readable_pipe cannot contain any further layers, it
  204. * simply returns a reference to itself.
  205. *
  206. * @return A reference to the lowest layer in the stack of layers. Ownership
  207. * is not transferred to the caller.
  208. */
  209. lowest_layer_type& lowest_layer()
  210. {
  211. return *this;
  212. }
  213. /// Get a const reference to the lowest layer.
  214. /**
  215. * This function returns a const reference to the lowest layer in a stack of
  216. * layers. Since a basic_readable_pipe cannot contain any further layers, it
  217. * simply returns a reference to itself.
  218. *
  219. * @return A const reference to the lowest layer in the stack of layers.
  220. * Ownership is not transferred to the caller.
  221. */
  222. const lowest_layer_type& lowest_layer() const
  223. {
  224. return *this;
  225. }
  226. /// Assign an existing native pipe to the pipe.
  227. /*
  228. * This function opens the pipe to hold an existing native pipe.
  229. *
  230. * @param native_pipe A native pipe.
  231. *
  232. * @throws asio::system_error Thrown on failure.
  233. */
  234. void assign(const native_handle_type& native_pipe)
  235. {
  236. asio::error_code ec;
  237. impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec);
  238. asio::detail::throw_error(ec, "assign");
  239. }
  240. /// Assign an existing native pipe to the pipe.
  241. /*
  242. * This function opens the pipe to hold an existing native pipe.
  243. *
  244. * @param native_pipe A native pipe.
  245. *
  246. * @param ec Set to indicate what error occurred, if any.
  247. */
  248. ASIO_SYNC_OP_VOID assign(const native_handle_type& native_pipe,
  249. asio::error_code& ec)
  250. {
  251. impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec);
  252. ASIO_SYNC_OP_VOID_RETURN(ec);
  253. }
  254. /// Determine whether the pipe is open.
  255. bool is_open() const
  256. {
  257. return impl_.get_service().is_open(impl_.get_implementation());
  258. }
  259. /// Close the pipe.
  260. /**
  261. * This function is used to close the pipe. Any asynchronous read operations
  262. * will be cancelled immediately, and will complete with the
  263. * asio::error::operation_aborted error.
  264. *
  265. * @throws asio::system_error Thrown on failure.
  266. */
  267. void close()
  268. {
  269. asio::error_code ec;
  270. impl_.get_service().close(impl_.get_implementation(), ec);
  271. asio::detail::throw_error(ec, "close");
  272. }
  273. /// Close the pipe.
  274. /**
  275. * This function is used to close the pipe. Any asynchronous read operations
  276. * will be cancelled immediately, and will complete with the
  277. * asio::error::operation_aborted error.
  278. *
  279. * @param ec Set to indicate what error occurred, if any.
  280. */
  281. ASIO_SYNC_OP_VOID close(asio::error_code& ec)
  282. {
  283. impl_.get_service().close(impl_.get_implementation(), ec);
  284. ASIO_SYNC_OP_VOID_RETURN(ec);
  285. }
  286. /// Get the native pipe representation.
  287. /**
  288. * This function may be used to obtain the underlying representation of the
  289. * pipe. This is intended to allow access to native pipe
  290. * functionality that is not otherwise provided.
  291. */
  292. native_handle_type native_handle()
  293. {
  294. return impl_.get_service().native_handle(impl_.get_implementation());
  295. }
  296. /// Cancel all asynchronous operations associated with the pipe.
  297. /**
  298. * This function causes all outstanding asynchronous read operations to finish
  299. * immediately, and the handlers for cancelled operations will be passed the
  300. * asio::error::operation_aborted error.
  301. *
  302. * @throws asio::system_error Thrown on failure.
  303. */
  304. void cancel()
  305. {
  306. asio::error_code ec;
  307. impl_.get_service().cancel(impl_.get_implementation(), ec);
  308. asio::detail::throw_error(ec, "cancel");
  309. }
  310. /// Cancel all asynchronous operations associated with the pipe.
  311. /**
  312. * This function causes all outstanding asynchronous read operations to finish
  313. * immediately, and the handlers for cancelled operations will be passed the
  314. * asio::error::operation_aborted error.
  315. *
  316. * @param ec Set to indicate what error occurred, if any.
  317. */
  318. ASIO_SYNC_OP_VOID cancel(asio::error_code& ec)
  319. {
  320. impl_.get_service().cancel(impl_.get_implementation(), ec);
  321. ASIO_SYNC_OP_VOID_RETURN(ec);
  322. }
  323. /// Read some data from the pipe.
  324. /**
  325. * This function is used to read data from the pipe. The function call will
  326. * block until one or more bytes of data has been read successfully, or until
  327. * an error occurs.
  328. *
  329. * @param buffers One or more buffers into which the data will be read.
  330. *
  331. * @returns The number of bytes read.
  332. *
  333. * @throws asio::system_error Thrown on failure. An error code of
  334. * asio::error::eof indicates that the connection was closed by the
  335. * peer.
  336. *
  337. * @note The read_some operation may not read all of the requested number of
  338. * bytes. Consider using the @ref read function if you need to ensure that
  339. * the requested amount of data is read before the blocking operation
  340. * completes.
  341. *
  342. * @par Example
  343. * To read into a single data buffer use the @ref buffer function as follows:
  344. * @code
  345. * basic_readable_pipe.read_some(asio::buffer(data, size));
  346. * @endcode
  347. * See the @ref buffer documentation for information on reading into multiple
  348. * buffers in one go, and how to use it with arrays, boost::array or
  349. * std::vector.
  350. */
  351. template <typename MutableBufferSequence>
  352. std::size_t read_some(const MutableBufferSequence& buffers)
  353. {
  354. asio::error_code ec;
  355. std::size_t s = impl_.get_service().read_some(
  356. impl_.get_implementation(), buffers, ec);
  357. asio::detail::throw_error(ec, "read_some");
  358. return s;
  359. }
  360. /// Read some data from the pipe.
  361. /**
  362. * This function is used to read data from the pipe. The function call will
  363. * block until one or more bytes of data has been read successfully, or until
  364. * an error occurs.
  365. *
  366. * @param buffers One or more buffers into which the data will be read.
  367. *
  368. * @param ec Set to indicate what error occurred, if any.
  369. *
  370. * @returns The number of bytes read. Returns 0 if an error occurred.
  371. *
  372. * @note The read_some operation may not read all of the requested number of
  373. * bytes. Consider using the @ref read function if you need to ensure that
  374. * the requested amount of data is read before the blocking operation
  375. * completes.
  376. */
  377. template <typename MutableBufferSequence>
  378. std::size_t read_some(const MutableBufferSequence& buffers,
  379. asio::error_code& ec)
  380. {
  381. return impl_.get_service().read_some(
  382. impl_.get_implementation(), buffers, ec);
  383. }
  384. /// Start an asynchronous read.
  385. /**
  386. * This function is used to asynchronously read data from the pipe. It is an
  387. * initiating function for an @ref asynchronous_operation, and always returns
  388. * immediately.
  389. *
  390. * @param buffers One or more buffers into which the data will be read.
  391. * Although the buffers object may be copied as necessary, ownership of the
  392. * underlying memory blocks is retained by the caller, which must guarantee
  393. * that they remain valid until the completion handler is called.
  394. *
  395. * @param token The @ref completion_token that will be used to produce a
  396. * completion handler, which will be called when the read completes.
  397. * Potential completion tokens include @ref use_future, @ref use_awaitable,
  398. * @ref yield_context, or a function object with the correct completion
  399. * signature. The function signature of the completion handler must be:
  400. * @code void handler(
  401. * const asio::error_code& error, // Result of operation.
  402. * std::size_t bytes_transferred // Number of bytes read.
  403. * ); @endcode
  404. * Regardless of whether the asynchronous operation completes immediately or
  405. * not, the completion handler will not be invoked from within this function.
  406. * On immediate completion, invocation of the handler will be performed in a
  407. * manner equivalent to using asio::post().
  408. *
  409. * @par Completion Signature
  410. * @code void(asio::error_code, std::size_t) @endcode
  411. *
  412. * @note The read operation may not read all of the requested number of bytes.
  413. * Consider using the @ref async_read function if you need to ensure that the
  414. * requested amount of data is read before the asynchronous operation
  415. * completes.
  416. *
  417. * @par Example
  418. * To read into a single data buffer use the @ref buffer function as follows:
  419. * @code
  420. * basic_readable_pipe.async_read_some(
  421. * asio::buffer(data, size), handler);
  422. * @endcode
  423. * See the @ref buffer documentation for information on reading into multiple
  424. * buffers in one go, and how to use it with arrays, boost::array or
  425. * std::vector.
  426. */
  427. template <typename MutableBufferSequence,
  428. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  429. std::size_t)) ReadToken
  430. ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  431. ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
  432. void (asio::error_code, std::size_t))
  433. async_read_some(const MutableBufferSequence& buffers,
  434. ASIO_MOVE_ARG(ReadToken) token
  435. ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
  436. {
  437. return async_initiate<ReadToken,
  438. void (asio::error_code, std::size_t)>(
  439. initiate_async_read_some(this), token, buffers);
  440. }
  441. private:
  442. // Disallow copying and assignment.
  443. basic_readable_pipe(const basic_readable_pipe&) ASIO_DELETED;
  444. basic_readable_pipe& operator=(const basic_readable_pipe&) ASIO_DELETED;
  445. class initiate_async_read_some
  446. {
  447. public:
  448. typedef Executor executor_type;
  449. explicit initiate_async_read_some(basic_readable_pipe* self)
  450. : self_(self)
  451. {
  452. }
  453. executor_type get_executor() const ASIO_NOEXCEPT
  454. {
  455. return self_->get_executor();
  456. }
  457. template <typename ReadHandler, typename MutableBufferSequence>
  458. void operator()(ASIO_MOVE_ARG(ReadHandler) handler,
  459. const MutableBufferSequence& buffers) const
  460. {
  461. // If you get an error on the following line it means that your handler
  462. // does not meet the documented type requirements for a ReadHandler.
  463. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  464. detail::non_const_lvalue<ReadHandler> handler2(handler);
  465. self_->impl_.get_service().async_read_some(
  466. self_->impl_.get_implementation(), buffers,
  467. handler2.value, self_->impl_.get_executor());
  468. }
  469. private:
  470. basic_readable_pipe* self_;
  471. };
  472. #if defined(ASIO_HAS_IOCP)
  473. detail::io_object_impl<detail::win_iocp_handle_service, Executor> impl_;
  474. #elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)
  475. detail::io_object_impl<detail::io_uring_descriptor_service, Executor> impl_;
  476. #else
  477. detail::io_object_impl<detail::reactive_descriptor_service, Executor> impl_;
  478. #endif
  479. };
  480. } // namespace asio
  481. #include "asio/detail/pop_options.hpp"
  482. #endif // defined(ASIO_HAS_PIPE)
  483. // || defined(GENERATING_DOCUMENTATION)
  484. #endif // ASIO_BASIC_READABLE_PIPE_HPP