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