basic_stream_handle.hpp 20 KB

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