|
||||
File indexing completed on 2025-01-18 09:29:03
0001 // 0002 // windows/basic_stream_handle.hpp 0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0004 // 0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) 0006 // 0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying 0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 0009 // 0010 0011 #ifndef BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP 0012 #define BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP 0013 0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 0015 # pragma once 0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 0017 0018 #include <boost/asio/detail/config.hpp> 0019 #include <boost/asio/windows/basic_overlapped_handle.hpp> 0020 0021 #if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \ 0022 || defined(GENERATING_DOCUMENTATION) 0023 0024 #include <boost/asio/detail/push_options.hpp> 0025 0026 namespace boost { 0027 namespace asio { 0028 namespace windows { 0029 0030 /// Provides stream-oriented handle functionality. 0031 /** 0032 * The windows::basic_stream_handle class provides asynchronous and blocking 0033 * stream-oriented handle functionality. 0034 * 0035 * @par Thread Safety 0036 * @e Distinct @e objects: Safe.@n 0037 * @e Shared @e objects: Unsafe. 0038 * 0039 * @par Concepts: 0040 * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. 0041 */ 0042 template <typename Executor = any_io_executor> 0043 class basic_stream_handle 0044 : public basic_overlapped_handle<Executor> 0045 { 0046 private: 0047 class initiate_async_write_some; 0048 class initiate_async_read_some; 0049 0050 public: 0051 /// The type of the executor associated with the object. 0052 typedef Executor executor_type; 0053 0054 /// Rebinds the handle type to another executor. 0055 template <typename Executor1> 0056 struct rebind_executor 0057 { 0058 /// The handle type when rebound to the specified executor. 0059 typedef basic_stream_handle<Executor1> other; 0060 }; 0061 0062 /// The native representation of a handle. 0063 #if defined(GENERATING_DOCUMENTATION) 0064 typedef implementation_defined native_handle_type; 0065 #else 0066 typedef boost::asio::detail::win_iocp_handle_service::native_handle_type 0067 native_handle_type; 0068 #endif 0069 0070 /// Construct a stream handle without opening it. 0071 /** 0072 * This constructor creates a stream handle without opening it. 0073 * 0074 * @param ex The I/O executor that the stream handle will use, by default, to 0075 * dispatch handlers for any asynchronous operations performed on the stream 0076 * handle. 0077 */ 0078 explicit basic_stream_handle(const executor_type& ex) 0079 : basic_overlapped_handle<Executor>(ex) 0080 { 0081 } 0082 0083 /// Construct a stream handle without opening it. 0084 /** 0085 * This constructor creates a stream handle without opening it. The handle 0086 * needs to be opened or assigned before data can be written to or read from 0087 * it. 0088 * 0089 * @param context An execution context which provides the I/O executor that 0090 * the stream handle will use, by default, to dispatch handlers for any 0091 * asynchronous operations performed on the stream handle. 0092 */ 0093 template <typename ExecutionContext> 0094 explicit basic_stream_handle(ExecutionContext& context, 0095 constraint_t< 0096 is_convertible<ExecutionContext&, execution_context&>::value, 0097 defaulted_constraint 0098 > = defaulted_constraint()) 0099 : basic_overlapped_handle<Executor>(context) 0100 { 0101 } 0102 0103 /// Construct a stream handle on an existing native handle. 0104 /** 0105 * This constructor creates a stream handle object to hold an existing native 0106 * handle. 0107 * 0108 * @param ex The I/O executor that the stream handle will use, by default, to 0109 * dispatch handlers for any asynchronous operations performed on the stream 0110 * handle. 0111 * 0112 * @param handle The new underlying handle implementation. 0113 * 0114 * @throws boost::system::system_error Thrown on failure. 0115 */ 0116 basic_stream_handle(const executor_type& ex, const native_handle_type& handle) 0117 : basic_overlapped_handle<Executor>(ex, handle) 0118 { 0119 } 0120 0121 /// Construct a stream handle on an existing native handle. 0122 /** 0123 * This constructor creates a stream handle object to hold an existing native 0124 * handle. 0125 * 0126 * @param context An execution context which provides the I/O executor that 0127 * the stream handle will use, by default, to dispatch handlers for any 0128 * asynchronous operations performed on the stream handle. 0129 * 0130 * @param handle The new underlying handle implementation. 0131 * 0132 * @throws boost::system::system_error Thrown on failure. 0133 */ 0134 template <typename ExecutionContext> 0135 basic_stream_handle(ExecutionContext& context, 0136 const native_handle_type& handle, 0137 constraint_t< 0138 is_convertible<ExecutionContext&, execution_context&>::value 0139 > = 0) 0140 : basic_overlapped_handle<Executor>(context, handle) 0141 { 0142 } 0143 0144 /// Move-construct a stream handle from another. 0145 /** 0146 * This constructor moves a stream handle from one object to another. 0147 * 0148 * @param other The other stream handle object from which the move 0149 * will occur. 0150 * 0151 * @note Following the move, the moved-from object is in the same state as if 0152 * constructed using the @c basic_stream_handle(const executor_type&) 0153 * constructor. 0154 */ 0155 basic_stream_handle(basic_stream_handle&& other) 0156 : basic_overlapped_handle<Executor>(std::move(other)) 0157 { 0158 } 0159 0160 /// Move-assign a stream handle from another. 0161 /** 0162 * This assignment operator moves a stream handle from one object to 0163 * another. 0164 * 0165 * @param other The other stream handle object from which the move will occur. 0166 * 0167 * @note Following the move, the moved-from object is in the same state as if 0168 * constructed using the @c basic_stream_handle(const executor_type&) 0169 * constructor. 0170 */ 0171 basic_stream_handle& operator=(basic_stream_handle&& other) 0172 { 0173 basic_overlapped_handle<Executor>::operator=(std::move(other)); 0174 return *this; 0175 } 0176 0177 /// Move-construct a stream handle from a handle of another executor type. 0178 /** 0179 * This constructor moves a stream handle from one object to another. 0180 * 0181 * @param other The other stream handle object from which the move 0182 * will occur. 0183 * 0184 * @note Following the move, the moved-from object is in the same state as if 0185 * constructed using the @c basic_stream_handle(const executor_type&) 0186 * constructor. 0187 */ 0188 template<typename Executor1> 0189 basic_stream_handle(basic_stream_handle<Executor1>&& other, 0190 constraint_t< 0191 is_convertible<Executor1, Executor>::value, 0192 defaulted_constraint 0193 > = defaulted_constraint()) 0194 : basic_overlapped_handle<Executor>(std::move(other)) 0195 { 0196 } 0197 0198 /// Move-assign a stream handle from a handle of another executor type. 0199 /** 0200 * This assignment operator moves a stream handle from one object to 0201 * another. 0202 * 0203 * @param other The other stream handle object from which the move will occur. 0204 * 0205 * @note Following the move, the moved-from object is in the same state as if 0206 * constructed using the @c basic_stream_handle(const executor_type&) 0207 * constructor. 0208 */ 0209 template<typename Executor1> 0210 constraint_t< 0211 is_convertible<Executor1, Executor>::value, 0212 basic_stream_handle& 0213 > operator=(basic_stream_handle<Executor1>&& other) 0214 { 0215 basic_overlapped_handle<Executor>::operator=(std::move(other)); 0216 return *this; 0217 } 0218 0219 /// Write some data to the handle. 0220 /** 0221 * This function is used to write data to the stream handle. The function call 0222 * will block until one or more bytes of the data has been written 0223 * successfully, or until an error occurs. 0224 * 0225 * @param buffers One or more data buffers to be written to the handle. 0226 * 0227 * @returns The number of bytes written. 0228 * 0229 * @throws boost::system::system_error Thrown on failure. An error code of 0230 * boost::asio::error::eof indicates that the connection was closed by the 0231 * peer. 0232 * 0233 * @note The write_some operation may not transmit all of the data to the 0234 * peer. Consider using the @ref write function if you need to ensure that 0235 * all data is written before the blocking operation completes. 0236 * 0237 * @par Example 0238 * To write a single data buffer use the @ref buffer function as follows: 0239 * @code 0240 * handle.write_some(boost::asio::buffer(data, size)); 0241 * @endcode 0242 * See the @ref buffer documentation for information on writing multiple 0243 * buffers in one go, and how to use it with arrays, boost::array or 0244 * std::vector. 0245 */ 0246 template <typename ConstBufferSequence> 0247 std::size_t write_some(const ConstBufferSequence& buffers) 0248 { 0249 boost::system::error_code ec; 0250 std::size_t s = this->impl_.get_service().write_some( 0251 this->impl_.get_implementation(), buffers, ec); 0252 boost::asio::detail::throw_error(ec, "write_some"); 0253 return s; 0254 } 0255 0256 /// Write some data to the handle. 0257 /** 0258 * This function is used to write data to the stream handle. The function call 0259 * will block until one or more bytes of the data has been written 0260 * successfully, or until an error occurs. 0261 * 0262 * @param buffers One or more data buffers to be written to the handle. 0263 * 0264 * @param ec Set to indicate what error occurred, if any. 0265 * 0266 * @returns The number of bytes written. Returns 0 if an error occurred. 0267 * 0268 * @note The write_some operation may not transmit all of the data to the 0269 * peer. Consider using the @ref write function if you need to ensure that 0270 * all data is written before the blocking operation completes. 0271 */ 0272 template <typename ConstBufferSequence> 0273 std::size_t write_some(const ConstBufferSequence& buffers, 0274 boost::system::error_code& ec) 0275 { 0276 return this->impl_.get_service().write_some( 0277 this->impl_.get_implementation(), buffers, ec); 0278 } 0279 0280 /// Start an asynchronous write. 0281 /** 0282 * This function is used to asynchronously write data to the stream handle. 0283 * It is an initiating function for an @ref asynchronous_operation, and always 0284 * returns immediately. 0285 * 0286 * @param buffers One or more data buffers to be written to the handle. 0287 * Although the buffers object may be copied as necessary, ownership of the 0288 * underlying memory blocks is retained by the caller, which must guarantee 0289 * that they remain valid until the completion handler is called. 0290 * 0291 * @param token The @ref completion_token that will be used to produce a 0292 * completion handler, which will be called when the write completes. 0293 * Potential completion tokens include @ref use_future, @ref use_awaitable, 0294 * @ref yield_context, or a function object with the correct completion 0295 * signature. The function signature of the completion handler must be: 0296 * @code void handler( 0297 * const boost::system::error_code& error, // Result of operation. 0298 * std::size_t bytes_transferred // Number of bytes written. 0299 * ); @endcode 0300 * Regardless of whether the asynchronous operation completes immediately or 0301 * not, the completion handler will not be invoked from within this function. 0302 * On immediate completion, invocation of the handler will be performed in a 0303 * manner equivalent to using boost::asio::post(). 0304 * 0305 * @par Completion Signature 0306 * @code void(boost::system::error_code, std::size_t) @endcode 0307 * 0308 * @note The write operation may not transmit all of the data to the peer. 0309 * Consider using the @ref async_write function if you need to ensure that all 0310 * data is written before the asynchronous operation completes. 0311 * 0312 * @par Example 0313 * To write a single data buffer use the @ref buffer function as follows: 0314 * @code 0315 * handle.async_write_some(boost::asio::buffer(data, size), handler); 0316 * @endcode 0317 * See the @ref buffer documentation for information on writing multiple 0318 * buffers in one go, and how to use it with arrays, boost::array or 0319 * std::vector. 0320 * 0321 * @par Per-Operation Cancellation 0322 * This asynchronous operation supports cancellation for the following 0323 * boost::asio::cancellation_type values: 0324 * 0325 * @li @c cancellation_type::terminal 0326 * 0327 * @li @c cancellation_type::partial 0328 * 0329 * @li @c cancellation_type::total 0330 */ 0331 template <typename ConstBufferSequence, 0332 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, 0333 std::size_t)) WriteToken = default_completion_token_t<executor_type>> 0334 auto async_write_some(const ConstBufferSequence& buffers, 0335 WriteToken&& token = default_completion_token_t<executor_type>()) 0336 -> decltype( 0337 async_initiate<WriteToken, 0338 void (boost::system::error_code, std::size_t)>( 0339 declval<initiate_async_write_some>(), token, buffers)) 0340 { 0341 return async_initiate<WriteToken, 0342 void (boost::system::error_code, std::size_t)>( 0343 initiate_async_write_some(this), token, buffers); 0344 } 0345 0346 /// Read some data from the handle. 0347 /** 0348 * This function is used to read data from the stream handle. The function 0349 * call will block until one or more bytes of data has been read successfully, 0350 * or until an error occurs. 0351 * 0352 * @param buffers One or more buffers into which the data will be read. 0353 * 0354 * @returns The number of bytes read. 0355 * 0356 * @throws boost::system::system_error Thrown on failure. An error code of 0357 * boost::asio::error::eof indicates that the connection was closed by the 0358 * peer. 0359 * 0360 * @note The read_some operation may not read all of the requested number of 0361 * bytes. Consider using the @ref read function if you need to ensure that 0362 * the requested amount of data is read before the blocking operation 0363 * completes. 0364 * 0365 * @par Example 0366 * To read into a single data buffer use the @ref buffer function as follows: 0367 * @code 0368 * handle.read_some(boost::asio::buffer(data, size)); 0369 * @endcode 0370 * See the @ref buffer documentation for information on reading into multiple 0371 * buffers in one go, and how to use it with arrays, boost::array or 0372 * std::vector. 0373 */ 0374 template <typename MutableBufferSequence> 0375 std::size_t read_some(const MutableBufferSequence& buffers) 0376 { 0377 boost::system::error_code ec; 0378 std::size_t s = this->impl_.get_service().read_some( 0379 this->impl_.get_implementation(), buffers, ec); 0380 boost::asio::detail::throw_error(ec, "read_some"); 0381 return s; 0382 } 0383 0384 /// Read some data from the handle. 0385 /** 0386 * This function is used to read data from the stream handle. The function 0387 * call will block until one or more bytes of data has been read successfully, 0388 * or until an error occurs. 0389 * 0390 * @param buffers One or more buffers into which the data will be read. 0391 * 0392 * @param ec Set to indicate what error occurred, if any. 0393 * 0394 * @returns The number of bytes read. Returns 0 if an error occurred. 0395 * 0396 * @note The read_some operation may not read all of the requested number of 0397 * bytes. Consider using the @ref read function if you need to ensure that 0398 * the requested amount of data is read before the blocking operation 0399 * completes. 0400 */ 0401 template <typename MutableBufferSequence> 0402 std::size_t read_some(const MutableBufferSequence& buffers, 0403 boost::system::error_code& ec) 0404 { 0405 return this->impl_.get_service().read_some( 0406 this->impl_.get_implementation(), buffers, ec); 0407 } 0408 0409 /// Start an asynchronous read. 0410 /** 0411 * This function is used to asynchronously read data from the stream handle. 0412 * It is an initiating function for an @ref asynchronous_operation, and always 0413 * returns immediately. 0414 * 0415 * @param buffers One or more buffers into which the data will be read. 0416 * Although the buffers object may be copied as necessary, ownership of the 0417 * underlying memory blocks is retained by the caller, which must guarantee 0418 * that they remain valid until the completion handler is called. 0419 * 0420 * @param token The @ref completion_token that will be used to produce a 0421 * completion handler, which will be called when the read completes. 0422 * Potential completion tokens include @ref use_future, @ref use_awaitable, 0423 * @ref yield_context, or a function object with the correct completion 0424 * signature. The function signature of the completion handler must be: 0425 * @code void handler( 0426 * const boost::system::error_code& error, // Result of operation. 0427 * std::size_t bytes_transferred // Number of bytes read. 0428 * ); @endcode 0429 * Regardless of whether the asynchronous operation completes immediately or 0430 * not, the completion handler will not be invoked from within this function. 0431 * On immediate completion, invocation of the handler will be performed in a 0432 * manner equivalent to using boost::asio::post(). 0433 * 0434 * @par Completion Signature 0435 * @code void(boost::system::error_code, std::size_t) @endcode 0436 * 0437 * @note The read operation may not read all of the requested number of bytes. 0438 * Consider using the @ref async_read function if you need to ensure that the 0439 * requested amount of data is read before the asynchronous operation 0440 * completes. 0441 * 0442 * @par Example 0443 * To read into a single data buffer use the @ref buffer function as follows: 0444 * @code 0445 * handle.async_read_some(boost::asio::buffer(data, size), handler); 0446 * @endcode 0447 * See the @ref buffer documentation for information on reading into multiple 0448 * buffers in one go, and how to use it with arrays, boost::array or 0449 * std::vector. 0450 * 0451 * @par Per-Operation Cancellation 0452 * This asynchronous operation supports cancellation for the following 0453 * boost::asio::cancellation_type values: 0454 * 0455 * @li @c cancellation_type::terminal 0456 * 0457 * @li @c cancellation_type::partial 0458 * 0459 * @li @c cancellation_type::total 0460 */ 0461 template <typename MutableBufferSequence, 0462 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, 0463 std::size_t)) ReadToken = default_completion_token_t<executor_type>> 0464 auto async_read_some(const MutableBufferSequence& buffers, 0465 ReadToken&& token = default_completion_token_t<executor_type>()) 0466 -> decltype( 0467 async_initiate<ReadToken, 0468 void (boost::system::error_code, std::size_t)>( 0469 declval<initiate_async_read_some>(), token, buffers)) 0470 { 0471 return async_initiate<ReadToken, 0472 void (boost::system::error_code, std::size_t)>( 0473 initiate_async_read_some(this), token, buffers); 0474 } 0475 0476 private: 0477 class initiate_async_write_some 0478 { 0479 public: 0480 typedef Executor executor_type; 0481 0482 explicit initiate_async_write_some(basic_stream_handle* self) 0483 : self_(self) 0484 { 0485 } 0486 0487 const executor_type& get_executor() const noexcept 0488 { 0489 return self_->get_executor(); 0490 } 0491 0492 template <typename WriteHandler, typename ConstBufferSequence> 0493 void operator()(WriteHandler&& handler, 0494 const ConstBufferSequence& buffers) const 0495 { 0496 // If you get an error on the following line it means that your handler 0497 // does not meet the documented type requirements for a WriteHandler. 0498 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; 0499 0500 detail::non_const_lvalue<WriteHandler> handler2(handler); 0501 self_->impl_.get_service().async_write_some( 0502 self_->impl_.get_implementation(), buffers, 0503 handler2.value, self_->impl_.get_executor()); 0504 } 0505 0506 private: 0507 basic_stream_handle* self_; 0508 }; 0509 0510 class initiate_async_read_some 0511 { 0512 public: 0513 typedef Executor executor_type; 0514 0515 explicit initiate_async_read_some(basic_stream_handle* self) 0516 : self_(self) 0517 { 0518 } 0519 0520 const executor_type& get_executor() const noexcept 0521 { 0522 return self_->get_executor(); 0523 } 0524 0525 template <typename ReadHandler, typename MutableBufferSequence> 0526 void operator()(ReadHandler&& handler, 0527 const MutableBufferSequence& buffers) const 0528 { 0529 // If you get an error on the following line it means that your handler 0530 // does not meet the documented type requirements for a ReadHandler. 0531 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; 0532 0533 detail::non_const_lvalue<ReadHandler> handler2(handler); 0534 self_->impl_.get_service().async_read_some( 0535 self_->impl_.get_implementation(), buffers, 0536 handler2.value, self_->impl_.get_executor()); 0537 } 0538 0539 private: 0540 basic_stream_handle* self_; 0541 }; 0542 }; 0543 0544 } // namespace windows 0545 } // namespace asio 0546 } // namespace boost 0547 0548 #include <boost/asio/detail/pop_options.hpp> 0549 0550 #endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) 0551 // || defined(GENERATING_DOCUMENTATION) 0552 0553 #endif // BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |