|
||||
File indexing completed on 2025-01-18 09:29:07
0001 // 0002 // basic_writable_pipe.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_BASIC_WRITABLE_PIPE_HPP 0012 #define BOOST_ASIO_BASIC_WRITABLE_PIPE_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 0020 #if defined(BOOST_ASIO_HAS_PIPE) \ 0021 || defined(GENERATING_DOCUMENTATION) 0022 0023 #include <string> 0024 #include <utility> 0025 #include <boost/asio/any_io_executor.hpp> 0026 #include <boost/asio/async_result.hpp> 0027 #include <boost/asio/detail/handler_type_requirements.hpp> 0028 #include <boost/asio/detail/io_object_impl.hpp> 0029 #include <boost/asio/detail/non_const_lvalue.hpp> 0030 #include <boost/asio/detail/throw_error.hpp> 0031 #include <boost/asio/detail/type_traits.hpp> 0032 #include <boost/asio/error.hpp> 0033 #include <boost/asio/execution_context.hpp> 0034 #if defined(BOOST_ASIO_HAS_IOCP) 0035 # include <boost/asio/detail/win_iocp_handle_service.hpp> 0036 #elif defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT) 0037 # include <boost/asio/detail/io_uring_descriptor_service.hpp> 0038 #else 0039 # include <boost/asio/detail/reactive_descriptor_service.hpp> 0040 #endif 0041 0042 #include <boost/asio/detail/push_options.hpp> 0043 0044 namespace boost { 0045 namespace asio { 0046 0047 /// Provides pipe functionality. 0048 /** 0049 * The basic_writable_pipe class provides a wrapper over pipe 0050 * functionality. 0051 * 0052 * @par Thread Safety 0053 * @e Distinct @e objects: Safe.@n 0054 * @e Shared @e objects: Unsafe. 0055 */ 0056 template <typename Executor = any_io_executor> 0057 class basic_writable_pipe 0058 { 0059 private: 0060 class initiate_async_write_some; 0061 0062 public: 0063 /// The type of the executor associated with the object. 0064 typedef Executor executor_type; 0065 0066 /// Rebinds the pipe type to another executor. 0067 template <typename Executor1> 0068 struct rebind_executor 0069 { 0070 /// The pipe type when rebound to the specified executor. 0071 typedef basic_writable_pipe<Executor1> other; 0072 }; 0073 0074 /// The native representation of a pipe. 0075 #if defined(GENERATING_DOCUMENTATION) 0076 typedef implementation_defined native_handle_type; 0077 #elif defined(BOOST_ASIO_HAS_IOCP) 0078 typedef detail::win_iocp_handle_service::native_handle_type 0079 native_handle_type; 0080 #elif defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT) 0081 typedef detail::io_uring_descriptor_service::native_handle_type 0082 native_handle_type; 0083 #else 0084 typedef detail::reactive_descriptor_service::native_handle_type 0085 native_handle_type; 0086 #endif 0087 0088 /// A basic_writable_pipe is always the lowest layer. 0089 typedef basic_writable_pipe lowest_layer_type; 0090 0091 /// Construct a basic_writable_pipe without opening it. 0092 /** 0093 * This constructor creates a pipe without opening it. 0094 * 0095 * @param ex The I/O executor that the pipe will use, by default, to dispatch 0096 * handlers for any asynchronous operations performed on the pipe. 0097 */ 0098 explicit basic_writable_pipe(const executor_type& ex) 0099 : impl_(0, ex) 0100 { 0101 } 0102 0103 /// Construct a basic_writable_pipe without opening it. 0104 /** 0105 * This constructor creates a pipe without opening it. 0106 * 0107 * @param context An execution context which provides the I/O executor that 0108 * the pipe will use, by default, to dispatch handlers for any asynchronous 0109 * operations performed on the pipe. 0110 */ 0111 template <typename ExecutionContext> 0112 explicit basic_writable_pipe(ExecutionContext& context, 0113 constraint_t< 0114 is_convertible<ExecutionContext&, execution_context&>::value, 0115 defaulted_constraint 0116 > = defaulted_constraint()) 0117 : impl_(0, 0, context) 0118 { 0119 } 0120 0121 /// Construct a basic_writable_pipe on an existing native pipe. 0122 /** 0123 * This constructor creates a pipe object to hold an existing native 0124 * pipe. 0125 * 0126 * @param ex The I/O executor that the pipe will use, by default, to 0127 * dispatch handlers for any asynchronous operations performed on the 0128 * pipe. 0129 * 0130 * @param native_pipe A native pipe. 0131 * 0132 * @throws boost::system::system_error Thrown on failure. 0133 */ 0134 basic_writable_pipe(const executor_type& ex, 0135 const native_handle_type& native_pipe) 0136 : impl_(0, ex) 0137 { 0138 boost::system::error_code ec; 0139 impl_.get_service().assign(impl_.get_implementation(), 0140 native_pipe, ec); 0141 boost::asio::detail::throw_error(ec, "assign"); 0142 } 0143 0144 /// Construct a basic_writable_pipe on an existing native pipe. 0145 /** 0146 * This constructor creates a pipe object to hold an existing native 0147 * pipe. 0148 * 0149 * @param context An execution context which provides the I/O executor that 0150 * the pipe will use, by default, to dispatch handlers for any 0151 * asynchronous operations performed on the pipe. 0152 * 0153 * @param native_pipe A native pipe. 0154 * 0155 * @throws boost::system::system_error Thrown on failure. 0156 */ 0157 template <typename ExecutionContext> 0158 basic_writable_pipe(ExecutionContext& context, 0159 const native_handle_type& native_pipe, 0160 constraint_t< 0161 is_convertible<ExecutionContext&, execution_context&>::value 0162 > = 0) 0163 : impl_(0, 0, context) 0164 { 0165 boost::system::error_code ec; 0166 impl_.get_service().assign(impl_.get_implementation(), 0167 native_pipe, ec); 0168 boost::asio::detail::throw_error(ec, "assign"); 0169 } 0170 0171 /// Move-construct a basic_writable_pipe from another. 0172 /** 0173 * This constructor moves a pipe from one object to another. 0174 * 0175 * @param other The other basic_writable_pipe object from which the move will 0176 * occur. 0177 * 0178 * @note Following the move, the moved-from object is in the same state as if 0179 * constructed using the @c basic_writable_pipe(const executor_type&) 0180 * constructor. 0181 */ 0182 basic_writable_pipe(basic_writable_pipe&& other) 0183 : impl_(std::move(other.impl_)) 0184 { 0185 } 0186 0187 /// Move-assign a basic_writable_pipe from another. 0188 /** 0189 * This assignment operator moves a pipe from one object to another. 0190 * 0191 * @param other The other basic_writable_pipe object from which the move will 0192 * occur. 0193 * 0194 * @note Following the move, the moved-from object is in the same state as if 0195 * constructed using the @c basic_writable_pipe(const executor_type&) 0196 * constructor. 0197 */ 0198 basic_writable_pipe& operator=(basic_writable_pipe&& other) 0199 { 0200 impl_ = std::move(other.impl_); 0201 return *this; 0202 } 0203 0204 // All pipes have access to each other's implementations. 0205 template <typename Executor1> 0206 friend class basic_writable_pipe; 0207 0208 /// Move-construct a basic_writable_pipe from a pipe of another executor type. 0209 /** 0210 * This constructor moves a pipe from one object to another. 0211 * 0212 * @param other The other basic_writable_pipe object from which the move will 0213 * occur. 0214 * 0215 * @note Following the move, the moved-from object is in the same state as if 0216 * constructed using the @c basic_writable_pipe(const executor_type&) 0217 * constructor. 0218 */ 0219 template <typename Executor1> 0220 basic_writable_pipe(basic_writable_pipe<Executor1>&& other, 0221 constraint_t< 0222 is_convertible<Executor1, Executor>::value, 0223 defaulted_constraint 0224 > = defaulted_constraint()) 0225 : impl_(std::move(other.impl_)) 0226 { 0227 } 0228 0229 /// Move-assign a basic_writable_pipe from a pipe of another executor type. 0230 /** 0231 * This assignment operator moves a pipe from one object to another. 0232 * 0233 * @param other The other basic_writable_pipe object from which the move will 0234 * occur. 0235 * 0236 * @note Following the move, the moved-from object is in the same state as if 0237 * constructed using the @c basic_writable_pipe(const executor_type&) 0238 * constructor. 0239 */ 0240 template <typename Executor1> 0241 constraint_t< 0242 is_convertible<Executor1, Executor>::value, 0243 basic_writable_pipe& 0244 > operator=(basic_writable_pipe<Executor1>&& other) 0245 { 0246 basic_writable_pipe tmp(std::move(other)); 0247 impl_ = std::move(tmp.impl_); 0248 return *this; 0249 } 0250 0251 /// Destroys the pipe. 0252 /** 0253 * This function destroys the pipe, cancelling any outstanding 0254 * asynchronous wait operations associated with the pipe as if by 0255 * calling @c cancel. 0256 */ 0257 ~basic_writable_pipe() 0258 { 0259 } 0260 0261 /// Get the executor associated with the object. 0262 const executor_type& get_executor() noexcept 0263 { 0264 return impl_.get_executor(); 0265 } 0266 0267 /// Get a reference to the lowest layer. 0268 /** 0269 * This function returns a reference to the lowest layer in a stack of 0270 * layers. Since a basic_writable_pipe cannot contain any further layers, it 0271 * simply returns a reference to itself. 0272 * 0273 * @return A reference to the lowest layer in the stack of layers. Ownership 0274 * is not transferred to the caller. 0275 */ 0276 lowest_layer_type& lowest_layer() 0277 { 0278 return *this; 0279 } 0280 0281 /// Get a const reference to the lowest layer. 0282 /** 0283 * This function returns a const reference to the lowest layer in a stack of 0284 * layers. Since a basic_writable_pipe cannot contain any further layers, it 0285 * simply returns a reference to itself. 0286 * 0287 * @return A const reference to the lowest layer in the stack of layers. 0288 * Ownership is not transferred to the caller. 0289 */ 0290 const lowest_layer_type& lowest_layer() const 0291 { 0292 return *this; 0293 } 0294 0295 /// Assign an existing native pipe to the pipe. 0296 /* 0297 * This function opens the pipe to hold an existing native pipe. 0298 * 0299 * @param native_pipe A native pipe. 0300 * 0301 * @throws boost::system::system_error Thrown on failure. 0302 */ 0303 void assign(const native_handle_type& native_pipe) 0304 { 0305 boost::system::error_code ec; 0306 impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec); 0307 boost::asio::detail::throw_error(ec, "assign"); 0308 } 0309 0310 /// Assign an existing native pipe to the pipe. 0311 /* 0312 * This function opens the pipe to hold an existing native pipe. 0313 * 0314 * @param native_pipe A native pipe. 0315 * 0316 * @param ec Set to indicate what error occurred, if any. 0317 */ 0318 BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& native_pipe, 0319 boost::system::error_code& ec) 0320 { 0321 impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec); 0322 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 0323 } 0324 0325 /// Determine whether the pipe is open. 0326 bool is_open() const 0327 { 0328 return impl_.get_service().is_open(impl_.get_implementation()); 0329 } 0330 0331 /// Close the pipe. 0332 /** 0333 * This function is used to close the pipe. Any asynchronous write operations 0334 * will be cancelled immediately, and will complete with the 0335 * boost::asio::error::operation_aborted error. 0336 * 0337 * @throws boost::system::system_error Thrown on failure. 0338 */ 0339 void close() 0340 { 0341 boost::system::error_code ec; 0342 impl_.get_service().close(impl_.get_implementation(), ec); 0343 boost::asio::detail::throw_error(ec, "close"); 0344 } 0345 0346 /// Close the pipe. 0347 /** 0348 * This function is used to close the pipe. Any asynchronous write operations 0349 * will be cancelled immediately, and will complete with the 0350 * boost::asio::error::operation_aborted error. 0351 * 0352 * @param ec Set to indicate what error occurred, if any. 0353 */ 0354 BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) 0355 { 0356 impl_.get_service().close(impl_.get_implementation(), ec); 0357 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 0358 } 0359 0360 /// Release ownership of the underlying native pipe. 0361 /** 0362 * This function causes all outstanding asynchronous write operations to 0363 * finish immediately, and the handlers for cancelled operations will be 0364 * passed the boost::asio::error::operation_aborted error. Ownership of the 0365 * native pipe is then transferred to the caller. 0366 * 0367 * @throws boost::system::system_error Thrown on failure. 0368 * 0369 * @note This function is unsupported on Windows versions prior to Windows 0370 * 8.1, and will fail with boost::asio::error::operation_not_supported on 0371 * these platforms. 0372 */ 0373 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ 0374 && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) 0375 __declspec(deprecated("This function always fails with " 0376 "operation_not_supported when used on Windows versions " 0377 "prior to Windows 8.1.")) 0378 #endif 0379 native_handle_type release() 0380 { 0381 boost::system::error_code ec; 0382 native_handle_type s = impl_.get_service().release( 0383 impl_.get_implementation(), ec); 0384 boost::asio::detail::throw_error(ec, "release"); 0385 return s; 0386 } 0387 0388 /// Release ownership of the underlying native pipe. 0389 /** 0390 * This function causes all outstanding asynchronous write operations to 0391 * finish immediately, and the handlers for cancelled operations will be 0392 * passed the boost::asio::error::operation_aborted error. Ownership of the 0393 * native pipe is then transferred to the caller. 0394 * 0395 * @param ec Set to indicate what error occurred, if any. 0396 * 0397 * @note This function is unsupported on Windows versions prior to Windows 0398 * 8.1, and will fail with boost::asio::error::operation_not_supported on 0399 * these platforms. 0400 */ 0401 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ 0402 && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) 0403 __declspec(deprecated("This function always fails with " 0404 "operation_not_supported when used on Windows versions " 0405 "prior to Windows 8.1.")) 0406 #endif 0407 native_handle_type release(boost::system::error_code& ec) 0408 { 0409 return impl_.get_service().release(impl_.get_implementation(), ec); 0410 } 0411 0412 /// Get the native pipe representation. 0413 /** 0414 * This function may be used to obtain the underlying representation of the 0415 * pipe. This is intended to allow access to native pipe 0416 * functionality that is not otherwise provided. 0417 */ 0418 native_handle_type native_handle() 0419 { 0420 return impl_.get_service().native_handle(impl_.get_implementation()); 0421 } 0422 0423 /// Cancel all asynchronous operations associated with the pipe. 0424 /** 0425 * This function causes all outstanding asynchronous write operations to 0426 * finish immediately, and the handlers for cancelled operations will be 0427 * passed the boost::asio::error::operation_aborted error. 0428 * 0429 * @throws boost::system::system_error Thrown on failure. 0430 */ 0431 void cancel() 0432 { 0433 boost::system::error_code ec; 0434 impl_.get_service().cancel(impl_.get_implementation(), ec); 0435 boost::asio::detail::throw_error(ec, "cancel"); 0436 } 0437 0438 /// Cancel all asynchronous operations associated with the pipe. 0439 /** 0440 * This function causes all outstanding asynchronous write operations to 0441 * finish immediately, and the handlers for cancelled operations will be 0442 * passed the boost::asio::error::operation_aborted error. 0443 * 0444 * @param ec Set to indicate what error occurred, if any. 0445 */ 0446 BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) 0447 { 0448 impl_.get_service().cancel(impl_.get_implementation(), ec); 0449 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 0450 } 0451 0452 /// Write some data to the pipe. 0453 /** 0454 * This function is used to write data to the pipe. The function call will 0455 * block until one or more bytes of the data has been written successfully, 0456 * or until an error occurs. 0457 * 0458 * @param buffers One or more data buffers to be written to the pipe. 0459 * 0460 * @returns The number of bytes written. 0461 * 0462 * @throws boost::system::system_error Thrown on failure. An error code of 0463 * boost::asio::error::eof indicates that the connection was closed by the 0464 * peer. 0465 * 0466 * @note The write_some operation may not transmit all of the data to the 0467 * peer. Consider using the @ref write function if you need to ensure that 0468 * all data is written before the blocking operation completes. 0469 * 0470 * @par Example 0471 * To write a single data buffer use the @ref buffer function as follows: 0472 * @code 0473 * pipe.write_some(boost::asio::buffer(data, size)); 0474 * @endcode 0475 * See the @ref buffer documentation for information on writing multiple 0476 * buffers in one go, and how to use it with arrays, boost::array or 0477 * std::vector. 0478 */ 0479 template <typename ConstBufferSequence> 0480 std::size_t write_some(const ConstBufferSequence& buffers) 0481 { 0482 boost::system::error_code ec; 0483 std::size_t s = impl_.get_service().write_some( 0484 impl_.get_implementation(), buffers, ec); 0485 boost::asio::detail::throw_error(ec, "write_some"); 0486 return s; 0487 } 0488 0489 /// Write some data to the pipe. 0490 /** 0491 * This function is used to write data to the pipe. The function call will 0492 * block until one or more bytes of the data has been written successfully, 0493 * or until an error occurs. 0494 * 0495 * @param buffers One or more data buffers to be written to the pipe. 0496 * 0497 * @param ec Set to indicate what error occurred, if any. 0498 * 0499 * @returns The number of bytes written. Returns 0 if an error occurred. 0500 * 0501 * @note The write_some operation may not transmit all of the data to the 0502 * peer. Consider using the @ref write function if you need to ensure that 0503 * all data is written before the blocking operation completes. 0504 */ 0505 template <typename ConstBufferSequence> 0506 std::size_t write_some(const ConstBufferSequence& buffers, 0507 boost::system::error_code& ec) 0508 { 0509 return impl_.get_service().write_some( 0510 impl_.get_implementation(), buffers, ec); 0511 } 0512 0513 /// Start an asynchronous write. 0514 /** 0515 * This function is used to asynchronously write data to the pipe. It is an 0516 * initiating function for an @ref asynchronous_operation, and always returns 0517 * immediately. 0518 * 0519 * @param buffers One or more data buffers to be written to the pipe. 0520 * Although the buffers object may be copied as necessary, ownership of the 0521 * underlying memory blocks is retained by the caller, which must guarantee 0522 * that they remain valid until the completion handler is called. 0523 * 0524 * @param token The @ref completion_token that will be used to produce a 0525 * completion handler, which will be called when the write completes. 0526 * Potential completion tokens include @ref use_future, @ref use_awaitable, 0527 * @ref yield_context, or a function object with the correct completion 0528 * signature. The function signature of the completion handler must be: 0529 * @code void handler( 0530 * const boost::system::error_code& error, // Result of operation. 0531 * std::size_t bytes_transferred // Number of bytes written. 0532 * ); @endcode 0533 * Regardless of whether the asynchronous operation completes immediately or 0534 * not, the completion handler will not be invoked from within this function. 0535 * On immediate completion, invocation of the handler will be performed in a 0536 * manner equivalent to using boost::asio::post(). 0537 * 0538 * @par Completion Signature 0539 * @code void(boost::system::error_code, std::size_t) @endcode 0540 * 0541 * @note The write operation may not transmit all of the data to the peer. 0542 * Consider using the @ref async_write function if you need to ensure that all 0543 * data is written before the asynchronous operation completes. 0544 * 0545 * @par Example 0546 * To write a single data buffer use the @ref buffer function as follows: 0547 * @code 0548 * pipe.async_write_some(boost::asio::buffer(data, size), handler); 0549 * @endcode 0550 * See the @ref buffer documentation for information on writing multiple 0551 * buffers in one go, and how to use it with arrays, boost::array or 0552 * std::vector. 0553 */ 0554 template <typename ConstBufferSequence, 0555 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, 0556 std::size_t)) WriteToken = default_completion_token_t<executor_type>> 0557 auto async_write_some(const ConstBufferSequence& buffers, 0558 WriteToken&& token = default_completion_token_t<executor_type>()) 0559 -> decltype( 0560 async_initiate<WriteToken, 0561 void (boost::system::error_code, std::size_t)>( 0562 declval<initiate_async_write_some>(), token, buffers)) 0563 { 0564 return async_initiate<WriteToken, 0565 void (boost::system::error_code, std::size_t)>( 0566 initiate_async_write_some(this), token, buffers); 0567 } 0568 0569 private: 0570 // Disallow copying and assignment. 0571 basic_writable_pipe(const basic_writable_pipe&) = delete; 0572 basic_writable_pipe& operator=(const basic_writable_pipe&) = delete; 0573 0574 class initiate_async_write_some 0575 { 0576 public: 0577 typedef Executor executor_type; 0578 0579 explicit initiate_async_write_some(basic_writable_pipe* self) 0580 : self_(self) 0581 { 0582 } 0583 0584 const executor_type& get_executor() const noexcept 0585 { 0586 return self_->get_executor(); 0587 } 0588 0589 template <typename WriteHandler, typename ConstBufferSequence> 0590 void operator()(WriteHandler&& handler, 0591 const ConstBufferSequence& buffers) const 0592 { 0593 // If you get an error on the following line it means that your handler 0594 // does not meet the documented type requirements for a WriteHandler. 0595 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; 0596 0597 detail::non_const_lvalue<WriteHandler> handler2(handler); 0598 self_->impl_.get_service().async_write_some( 0599 self_->impl_.get_implementation(), buffers, 0600 handler2.value, self_->impl_.get_executor()); 0601 } 0602 0603 private: 0604 basic_writable_pipe* self_; 0605 }; 0606 0607 #if defined(BOOST_ASIO_HAS_IOCP) 0608 detail::io_object_impl<detail::win_iocp_handle_service, Executor> impl_; 0609 #elif defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT) 0610 detail::io_object_impl<detail::io_uring_descriptor_service, Executor> impl_; 0611 #else 0612 detail::io_object_impl<detail::reactive_descriptor_service, Executor> impl_; 0613 #endif 0614 }; 0615 0616 } // namespace asio 0617 } // namespace boost 0618 0619 #include <boost/asio/detail/pop_options.hpp> 0620 0621 #endif // defined(BOOST_ASIO_HAS_PIPE) 0622 // || defined(GENERATING_DOCUMENTATION) 0623 0624 #endif // BOOST_ASIO_BASIC_WRITABLE_PIPE_HPP
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |