basic_stream_handle.hpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. //
  2. // windows/basic_stream_handle.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2023 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_WINDOWS_BASIC_STREAM_HANDLE_HPP
  11. #define ASIO_WINDOWS_BASIC_STREAM_HANDLE_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. #include "asio/windows/basic_overlapped_handle.hpp"
  17. #if defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \
  18. || defined(GENERATING_DOCUMENTATION)
  19. #include "asio/detail/push_options.hpp"
  20. namespace asio {
  21. namespace windows {
  22. /// Provides stream-oriented handle functionality.
  23. /**
  24. * The windows::basic_stream_handle class provides asynchronous and blocking
  25. * stream-oriented handle functionality.
  26. *
  27. * @par Thread Safety
  28. * @e Distinct @e objects: Safe.@n
  29. * @e Shared @e objects: Unsafe.
  30. *
  31. * @par Concepts:
  32. * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
  33. */
  34. template <typename Executor = any_io_executor>
  35. class basic_stream_handle
  36. : public basic_overlapped_handle<Executor>
  37. {
  38. private:
  39. class initiate_async_write_some;
  40. class initiate_async_read_some;
  41. public:
  42. /// The type of the executor associated with the object.
  43. typedef Executor executor_type;
  44. /// Rebinds the handle type to another executor.
  45. template <typename Executor1>
  46. struct rebind_executor
  47. {
  48. /// The handle type when rebound to the specified executor.
  49. typedef basic_stream_handle<Executor1> other;
  50. };
  51. /// The native representation of a handle.
  52. #if defined(GENERATING_DOCUMENTATION)
  53. typedef implementation_defined native_handle_type;
  54. #else
  55. typedef asio::detail::win_iocp_handle_service::native_handle_type
  56. native_handle_type;
  57. #endif
  58. /// Construct a stream handle without opening it.
  59. /**
  60. * This constructor creates a stream handle without opening it.
  61. *
  62. * @param ex The I/O executor that the stream handle will use, by default, to
  63. * dispatch handlers for any asynchronous operations performed on the stream
  64. * handle.
  65. */
  66. explicit basic_stream_handle(const executor_type& ex)
  67. : basic_overlapped_handle<Executor>(ex)
  68. {
  69. }
  70. /// Construct a stream handle without opening it.
  71. /**
  72. * This constructor creates a stream handle without opening it. The handle
  73. * needs to be opened or assigned before data can be written to or read from
  74. * it.
  75. *
  76. * @param context An execution context which provides the I/O executor that
  77. * the stream handle will use, by default, to dispatch handlers for any
  78. * asynchronous operations performed on the stream handle.
  79. */
  80. template <typename ExecutionContext>
  81. explicit basic_stream_handle(ExecutionContext& context,
  82. constraint_t<
  83. is_convertible<ExecutionContext&, execution_context&>::value,
  84. defaulted_constraint
  85. > = defaulted_constraint())
  86. : basic_overlapped_handle<Executor>(context)
  87. {
  88. }
  89. /// Construct a stream handle on an existing native handle.
  90. /**
  91. * This constructor creates a stream handle object to hold an existing native
  92. * handle.
  93. *
  94. * @param ex The I/O executor that the stream handle will use, by default, to
  95. * dispatch handlers for any asynchronous operations performed on the stream
  96. * handle.
  97. *
  98. * @param handle The new underlying handle implementation.
  99. *
  100. * @throws asio::system_error Thrown on failure.
  101. */
  102. basic_stream_handle(const executor_type& ex, const native_handle_type& handle)
  103. : basic_overlapped_handle<Executor>(ex, handle)
  104. {
  105. }
  106. /// Construct a stream handle on an existing native handle.
  107. /**
  108. * This constructor creates a stream handle object to hold an existing native
  109. * handle.
  110. *
  111. * @param context An execution context which provides the I/O executor that
  112. * the stream handle will use, by default, to dispatch handlers for any
  113. * asynchronous operations performed on the stream handle.
  114. *
  115. * @param handle The new underlying handle implementation.
  116. *
  117. * @throws asio::system_error Thrown on failure.
  118. */
  119. template <typename ExecutionContext>
  120. basic_stream_handle(ExecutionContext& context,
  121. const native_handle_type& handle,
  122. constraint_t<
  123. is_convertible<ExecutionContext&, execution_context&>::value
  124. > = 0)
  125. : basic_overlapped_handle<Executor>(context, handle)
  126. {
  127. }
  128. /// Move-construct a stream handle from another.
  129. /**
  130. * This constructor moves a stream handle from one object to another.
  131. *
  132. * @param other The other stream handle object from which the move
  133. * will occur.
  134. *
  135. * @note Following the move, the moved-from object is in the same state as if
  136. * constructed using the @c basic_stream_handle(const executor_type&)
  137. * constructor.
  138. */
  139. basic_stream_handle(basic_stream_handle&& other)
  140. : basic_overlapped_handle<Executor>(std::move(other))
  141. {
  142. }
  143. /// Move-assign a stream handle from another.
  144. /**
  145. * This assignment operator moves a stream handle from one object to
  146. * another.
  147. *
  148. * @param other The other stream handle object from which the move will occur.
  149. *
  150. * @note Following the move, the moved-from object is in the same state as if
  151. * constructed using the @c basic_stream_handle(const executor_type&)
  152. * constructor.
  153. */
  154. basic_stream_handle& operator=(basic_stream_handle&& other)
  155. {
  156. basic_overlapped_handle<Executor>::operator=(std::move(other));
  157. return *this;
  158. }
  159. /// Move-construct a stream handle from a handle of another executor type.
  160. /**
  161. * This constructor moves a stream handle from one object to another.
  162. *
  163. * @param other The other stream handle object from which the move
  164. * will occur.
  165. *
  166. * @note Following the move, the moved-from object is in the same state as if
  167. * constructed using the @c basic_stream_handle(const executor_type&)
  168. * constructor.
  169. */
  170. template<typename Executor1>
  171. basic_stream_handle(basic_stream_handle<Executor1>&& other,
  172. constraint_t<
  173. is_convertible<Executor1, Executor>::value,
  174. defaulted_constraint
  175. > = defaulted_constraint())
  176. : basic_overlapped_handle<Executor>(std::move(other))
  177. {
  178. }
  179. /// Move-assign a stream handle from a handle of another executor type.
  180. /**
  181. * This assignment operator moves a stream handle from one object to
  182. * another.
  183. *
  184. * @param other The other stream handle object from which the move will occur.
  185. *
  186. * @note Following the move, the moved-from object is in the same state as if
  187. * constructed using the @c basic_stream_handle(const executor_type&)
  188. * constructor.
  189. */
  190. template<typename Executor1>
  191. constraint_t<
  192. is_convertible<Executor1, Executor>::value,
  193. basic_stream_handle&
  194. > operator=(basic_stream_handle<Executor1>&& other)
  195. {
  196. basic_overlapped_handle<Executor>::operator=(std::move(other));
  197. return *this;
  198. }
  199. /// Write some data to the handle.
  200. /**
  201. * This function is used to write data to the stream handle. The function call
  202. * will block until one or more bytes of the data has been written
  203. * successfully, or until an error occurs.
  204. *
  205. * @param buffers One or more data buffers to be written to the handle.
  206. *
  207. * @returns The number of bytes written.
  208. *
  209. * @throws asio::system_error Thrown on failure. An error code of
  210. * asio::error::eof indicates that the connection was closed by the
  211. * peer.
  212. *
  213. * @note The write_some operation may not transmit all of the data to the
  214. * peer. Consider using the @ref write function if you need to ensure that
  215. * all data is written before the blocking operation completes.
  216. *
  217. * @par Example
  218. * To write a single data buffer use the @ref buffer function as follows:
  219. * @code
  220. * handle.write_some(asio::buffer(data, size));
  221. * @endcode
  222. * See the @ref buffer documentation for information on writing multiple
  223. * buffers in one go, and how to use it with arrays, boost::array or
  224. * std::vector.
  225. */
  226. template <typename ConstBufferSequence>
  227. std::size_t write_some(const ConstBufferSequence& buffers)
  228. {
  229. asio::error_code ec;
  230. std::size_t s = this->impl_.get_service().write_some(
  231. this->impl_.get_implementation(), buffers, ec);
  232. asio::detail::throw_error(ec, "write_some");
  233. return s;
  234. }
  235. /// Write some data to the handle.
  236. /**
  237. * This function is used to write data to the stream handle. The function call
  238. * will block until one or more bytes of the data has been written
  239. * successfully, or until an error occurs.
  240. *
  241. * @param buffers One or more data buffers to be written to the handle.
  242. *
  243. * @param ec Set to indicate what error occurred, if any.
  244. *
  245. * @returns The number of bytes written. Returns 0 if an error occurred.
  246. *
  247. * @note The write_some operation may not transmit all of the data to the
  248. * peer. Consider using the @ref write function if you need to ensure that
  249. * all data is written before the blocking operation completes.
  250. */
  251. template <typename ConstBufferSequence>
  252. std::size_t write_some(const ConstBufferSequence& buffers,
  253. asio::error_code& ec)
  254. {
  255. return this->impl_.get_service().write_some(
  256. this->impl_.get_implementation(), buffers, ec);
  257. }
  258. /// Start an asynchronous write.
  259. /**
  260. * This function is used to asynchronously write data to the stream handle.
  261. * It is an initiating function for an @ref asynchronous_operation, and always
  262. * returns immediately.
  263. *
  264. * @param buffers One or more data buffers to be written to the handle.
  265. * Although the buffers object may be copied as necessary, ownership of the
  266. * underlying memory blocks is retained by the caller, which must guarantee
  267. * that they remain valid until the completion handler is called.
  268. *
  269. * @param token The @ref completion_token that will be used to produce a
  270. * completion handler, which will be called when the write completes.
  271. * Potential completion tokens include @ref use_future, @ref use_awaitable,
  272. * @ref yield_context, or a function object with the correct completion
  273. * signature. The function signature of the completion handler must be:
  274. * @code void handler(
  275. * const asio::error_code& error, // Result of operation.
  276. * std::size_t bytes_transferred // Number of bytes written.
  277. * ); @endcode
  278. * Regardless of whether the asynchronous operation completes immediately or
  279. * not, the completion handler will not be invoked from within this function.
  280. * On immediate completion, invocation of the handler will be performed in a
  281. * manner equivalent to using asio::post().
  282. *
  283. * @par Completion Signature
  284. * @code void(asio::error_code, std::size_t) @endcode
  285. *
  286. * @note The write operation may not transmit all of the data to the peer.
  287. * Consider using the @ref async_write function if you need to ensure that all
  288. * data is written before the asynchronous operation completes.
  289. *
  290. * @par Example
  291. * To write a single data buffer use the @ref buffer function as follows:
  292. * @code
  293. * handle.async_write_some(asio::buffer(data, size), handler);
  294. * @endcode
  295. * See the @ref buffer documentation for information on writing multiple
  296. * buffers in one go, and how to use it with arrays, boost::array or
  297. * std::vector.
  298. *
  299. * @par Per-Operation Cancellation
  300. * This asynchronous operation supports cancellation for the following
  301. * asio::cancellation_type values:
  302. *
  303. * @li @c cancellation_type::terminal
  304. *
  305. * @li @c cancellation_type::partial
  306. *
  307. * @li @c cancellation_type::total
  308. */
  309. template <typename ConstBufferSequence,
  310. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  311. std::size_t)) WriteToken = default_completion_token_t<executor_type>>
  312. auto async_write_some(const ConstBufferSequence& buffers,
  313. WriteToken&& token = default_completion_token_t<executor_type>())
  314. -> decltype(
  315. async_initiate<WriteToken,
  316. void (asio::error_code, std::size_t)>(
  317. declval<initiate_async_write_some>(), token, buffers))
  318. {
  319. return async_initiate<WriteToken,
  320. void (asio::error_code, std::size_t)>(
  321. initiate_async_write_some(this), token, buffers);
  322. }
  323. /// Read some data from the handle.
  324. /**
  325. * This function is used to read data from the stream handle. The function
  326. * call will block until one or more bytes of data has been read successfully,
  327. * or until 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. * handle.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 = this->impl_.get_service().read_some(
  356. this->impl_.get_implementation(), buffers, ec);
  357. asio::detail::throw_error(ec, "read_some");
  358. return s;
  359. }
  360. /// Read some data from the handle.
  361. /**
  362. * This function is used to read data from the stream handle. The function
  363. * call will block until one or more bytes of data has been read successfully,
  364. * or until 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 this->impl_.get_service().read_some(
  382. this->impl_.get_implementation(), buffers, ec);
  383. }
  384. /// Start an asynchronous read.
  385. /**
  386. * This function is used to asynchronously read data from the stream handle.
  387. * It is an initiating function for an @ref asynchronous_operation, and always
  388. * returns 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. * handle.async_read_some(asio::buffer(data, size), handler);
  421. * @endcode
  422. * See the @ref buffer documentation for information on reading into multiple
  423. * buffers in one go, and how to use it with arrays, boost::array or
  424. * std::vector.
  425. *
  426. * @par Per-Operation Cancellation
  427. * This asynchronous operation supports cancellation for the following
  428. * asio::cancellation_type values:
  429. *
  430. * @li @c cancellation_type::terminal
  431. *
  432. * @li @c cancellation_type::partial
  433. *
  434. * @li @c cancellation_type::total
  435. */
  436. template <typename MutableBufferSequence,
  437. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  438. std::size_t)) ReadToken = default_completion_token_t<executor_type>>
  439. auto async_read_some(const MutableBufferSequence& buffers,
  440. ReadToken&& token = default_completion_token_t<executor_type>())
  441. -> decltype(
  442. async_initiate<ReadToken,
  443. void (asio::error_code, std::size_t)>(
  444. declval<initiate_async_read_some>(), token, buffers))
  445. {
  446. return async_initiate<ReadToken,
  447. void (asio::error_code, std::size_t)>(
  448. initiate_async_read_some(this), token, buffers);
  449. }
  450. private:
  451. class initiate_async_write_some
  452. {
  453. public:
  454. typedef Executor executor_type;
  455. explicit initiate_async_write_some(basic_stream_handle* self)
  456. : self_(self)
  457. {
  458. }
  459. const executor_type& get_executor() const noexcept
  460. {
  461. return self_->get_executor();
  462. }
  463. template <typename WriteHandler, typename ConstBufferSequence>
  464. void operator()(WriteHandler&& handler,
  465. const ConstBufferSequence& buffers) const
  466. {
  467. // If you get an error on the following line it means that your handler
  468. // does not meet the documented type requirements for a WriteHandler.
  469. ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  470. detail::non_const_lvalue<WriteHandler> handler2(handler);
  471. self_->impl_.get_service().async_write_some(
  472. self_->impl_.get_implementation(), buffers,
  473. handler2.value, self_->impl_.get_executor());
  474. }
  475. private:
  476. basic_stream_handle* self_;
  477. };
  478. class initiate_async_read_some
  479. {
  480. public:
  481. typedef Executor executor_type;
  482. explicit initiate_async_read_some(basic_stream_handle* self)
  483. : self_(self)
  484. {
  485. }
  486. const executor_type& get_executor() const noexcept
  487. {
  488. return self_->get_executor();
  489. }
  490. template <typename ReadHandler, typename MutableBufferSequence>
  491. void operator()(ReadHandler&& handler,
  492. const MutableBufferSequence& buffers) const
  493. {
  494. // If you get an error on the following line it means that your handler
  495. // does not meet the documented type requirements for a ReadHandler.
  496. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  497. detail::non_const_lvalue<ReadHandler> handler2(handler);
  498. self_->impl_.get_service().async_read_some(
  499. self_->impl_.get_implementation(), buffers,
  500. handler2.value, self_->impl_.get_executor());
  501. }
  502. private:
  503. basic_stream_handle* self_;
  504. };
  505. };
  506. } // namespace windows
  507. } // namespace asio
  508. #include "asio/detail/pop_options.hpp"
  509. #endif // defined(ASIO_HAS_WINDOWS_STREAM_HANDLE)
  510. // || defined(GENERATING_DOCUMENTATION)
  511. #endif // ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP