|
||||
File indexing completed on 2025-01-30 09:33:35
0001 // 0002 // posix/basic_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_DESCRIPTOR_HPP 0012 #define BOOST_ASIO_POSIX_BASIC_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 0020 #if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \ 0021 || defined(GENERATING_DOCUMENTATION) 0022 0023 #include <utility> 0024 #include <boost/asio/any_io_executor.hpp> 0025 #include <boost/asio/async_result.hpp> 0026 #include <boost/asio/detail/handler_type_requirements.hpp> 0027 #include <boost/asio/detail/io_object_impl.hpp> 0028 #include <boost/asio/detail/non_const_lvalue.hpp> 0029 #include <boost/asio/detail/throw_error.hpp> 0030 #include <boost/asio/error.hpp> 0031 #include <boost/asio/execution_context.hpp> 0032 #include <boost/asio/posix/descriptor_base.hpp> 0033 0034 #if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT) 0035 # include <boost/asio/detail/io_uring_descriptor_service.hpp> 0036 #else // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT) 0037 # include <boost/asio/detail/reactive_descriptor_service.hpp> 0038 #endif // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT) 0039 0040 #include <boost/asio/detail/push_options.hpp> 0041 0042 namespace boost { 0043 namespace asio { 0044 namespace posix { 0045 0046 /// Provides POSIX descriptor functionality. 0047 /** 0048 * The posix::basic_descriptor class template provides the ability to wrap a 0049 * POSIX descriptor. 0050 * 0051 * @par Thread Safety 0052 * @e Distinct @e objects: Safe.@n 0053 * @e Shared @e objects: Unsafe. 0054 */ 0055 template <typename Executor = any_io_executor> 0056 class basic_descriptor 0057 : public descriptor_base 0058 { 0059 private: 0060 class initiate_async_wait; 0061 0062 public: 0063 /// The type of the executor associated with the object. 0064 typedef Executor executor_type; 0065 0066 /// Rebinds the descriptor type to another executor. 0067 template <typename Executor1> 0068 struct rebind_executor 0069 { 0070 /// The descriptor type when rebound to the specified executor. 0071 typedef basic_descriptor<Executor1> other; 0072 }; 0073 0074 /// The native representation of a descriptor. 0075 #if defined(GENERATING_DOCUMENTATION) 0076 typedef implementation_defined native_handle_type; 0077 #elif defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT) 0078 typedef detail::io_uring_descriptor_service::native_handle_type 0079 native_handle_type; 0080 #else // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT) 0081 typedef detail::reactive_descriptor_service::native_handle_type 0082 native_handle_type; 0083 #endif // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT) 0084 0085 /// A descriptor is always the lowest layer. 0086 typedef basic_descriptor lowest_layer_type; 0087 0088 /// Construct a descriptor without opening it. 0089 /** 0090 * This constructor creates a descriptor without opening it. 0091 * 0092 * @param ex The I/O executor that the descriptor will use, by default, to 0093 * dispatch handlers for any asynchronous operations performed on the 0094 * descriptor. 0095 */ 0096 explicit basic_descriptor(const executor_type& ex) 0097 : impl_(0, ex) 0098 { 0099 } 0100 0101 /// Construct a descriptor without opening it. 0102 /** 0103 * This constructor creates a descriptor without opening it. 0104 * 0105 * @param context An execution context which provides the I/O executor that 0106 * the descriptor will use, by default, to dispatch handlers for any 0107 * asynchronous operations performed on the descriptor. 0108 */ 0109 template <typename ExecutionContext> 0110 explicit basic_descriptor(ExecutionContext& context, 0111 constraint_t< 0112 is_convertible<ExecutionContext&, execution_context&>::value, 0113 defaulted_constraint 0114 > = defaulted_constraint()) 0115 : impl_(0, 0, context) 0116 { 0117 } 0118 0119 /// Construct a descriptor on an existing native descriptor. 0120 /** 0121 * This constructor creates a descriptor object to hold an existing native 0122 * descriptor. 0123 * 0124 * @param ex The I/O executor that the descriptor will use, by default, to 0125 * dispatch handlers for any asynchronous operations performed on the 0126 * descriptor. 0127 * 0128 * @param native_descriptor A native descriptor. 0129 * 0130 * @throws boost::system::system_error Thrown on failure. 0131 */ 0132 basic_descriptor(const executor_type& ex, 0133 const native_handle_type& native_descriptor) 0134 : impl_(0, ex) 0135 { 0136 boost::system::error_code ec; 0137 impl_.get_service().assign(impl_.get_implementation(), 0138 native_descriptor, ec); 0139 boost::asio::detail::throw_error(ec, "assign"); 0140 } 0141 0142 /// Construct a descriptor on an existing native descriptor. 0143 /** 0144 * This constructor creates a descriptor object to hold an existing native 0145 * descriptor. 0146 * 0147 * @param context An execution context which provides the I/O executor that 0148 * the descriptor will use, by default, to dispatch handlers for any 0149 * asynchronous operations performed on the descriptor. 0150 * 0151 * @param native_descriptor A native descriptor. 0152 * 0153 * @throws boost::system::system_error Thrown on failure. 0154 */ 0155 template <typename ExecutionContext> 0156 basic_descriptor(ExecutionContext& context, 0157 const native_handle_type& native_descriptor, 0158 constraint_t< 0159 is_convertible<ExecutionContext&, execution_context&>::value 0160 > = 0) 0161 : impl_(0, 0, context) 0162 { 0163 boost::system::error_code ec; 0164 impl_.get_service().assign(impl_.get_implementation(), 0165 native_descriptor, ec); 0166 boost::asio::detail::throw_error(ec, "assign"); 0167 } 0168 0169 /// Move-construct a descriptor from another. 0170 /** 0171 * This constructor moves a descriptor from one object to another. 0172 * 0173 * @param other The other descriptor object from which the move will 0174 * occur. 0175 * 0176 * @note Following the move, the moved-from object is in the same state as if 0177 * constructed using the @c basic_descriptor(const executor_type&) 0178 * constructor. 0179 */ 0180 basic_descriptor(basic_descriptor&& other) noexcept 0181 : impl_(std::move(other.impl_)) 0182 { 0183 } 0184 0185 /// Move-assign a descriptor from another. 0186 /** 0187 * This assignment operator moves a descriptor from one object to another. 0188 * 0189 * @param other The other descriptor object from which the move will 0190 * occur. 0191 * 0192 * @note Following the move, the moved-from object is in the same state as if 0193 * constructed using the @c basic_descriptor(const executor_type&) 0194 * constructor. 0195 */ 0196 basic_descriptor& operator=(basic_descriptor&& other) 0197 { 0198 impl_ = std::move(other.impl_); 0199 return *this; 0200 } 0201 0202 // All descriptors have access to each other's implementations. 0203 template <typename Executor1> 0204 friend class basic_descriptor; 0205 0206 /// Move-construct a basic_descriptor from a descriptor of another executor 0207 /// type. 0208 /** 0209 * This constructor moves a descriptor from one object to another. 0210 * 0211 * @param other The other basic_descriptor object from which the move will 0212 * occur. 0213 * 0214 * @note Following the move, the moved-from object is in the same state as if 0215 * constructed using the @c basic_descriptor(const executor_type&) 0216 * constructor. 0217 */ 0218 template <typename Executor1> 0219 basic_descriptor(basic_descriptor<Executor1>&& other, 0220 constraint_t< 0221 is_convertible<Executor1, Executor>::value, 0222 defaulted_constraint 0223 > = defaulted_constraint()) 0224 : impl_(std::move(other.impl_)) 0225 { 0226 } 0227 0228 /// Move-assign a basic_descriptor from a descriptor of another executor type. 0229 /** 0230 * This assignment operator moves a descriptor from one object to another. 0231 * 0232 * @param other The other basic_descriptor object from which the move will 0233 * occur. 0234 * 0235 * @note Following the move, the moved-from object is in the same state as if 0236 * constructed using the @c basic_descriptor(const executor_type&) 0237 * constructor. 0238 */ 0239 template <typename Executor1> 0240 constraint_t< 0241 is_convertible<Executor1, Executor>::value, 0242 basic_descriptor& 0243 > operator=(basic_descriptor<Executor1> && other) 0244 { 0245 basic_descriptor tmp(std::move(other)); 0246 impl_ = std::move(tmp.impl_); 0247 return *this; 0248 } 0249 0250 /// Get the executor associated with the object. 0251 const executor_type& get_executor() noexcept 0252 { 0253 return impl_.get_executor(); 0254 } 0255 0256 /// Get a reference to the lowest layer. 0257 /** 0258 * This function returns a reference to the lowest layer in a stack of 0259 * layers. Since a descriptor cannot contain any further layers, it 0260 * simply returns a reference to itself. 0261 * 0262 * @return A reference to the lowest layer in the stack of layers. Ownership 0263 * is not transferred to the caller. 0264 */ 0265 lowest_layer_type& lowest_layer() 0266 { 0267 return *this; 0268 } 0269 0270 /// Get a const reference to the lowest layer. 0271 /** 0272 * This function returns a const reference to the lowest layer in a stack of 0273 * layers. Since a descriptor cannot contain any further layers, it 0274 * simply returns a reference to itself. 0275 * 0276 * @return A const reference to the lowest layer in the stack of layers. 0277 * Ownership is not transferred to the caller. 0278 */ 0279 const lowest_layer_type& lowest_layer() const 0280 { 0281 return *this; 0282 } 0283 0284 /// Assign an existing native descriptor to the descriptor. 0285 /* 0286 * This function opens the descriptor to hold an existing native descriptor. 0287 * 0288 * @param native_descriptor A native descriptor. 0289 * 0290 * @throws boost::system::system_error Thrown on failure. 0291 */ 0292 void assign(const native_handle_type& native_descriptor) 0293 { 0294 boost::system::error_code ec; 0295 impl_.get_service().assign(impl_.get_implementation(), 0296 native_descriptor, ec); 0297 boost::asio::detail::throw_error(ec, "assign"); 0298 } 0299 0300 /// Assign an existing native descriptor to the descriptor. 0301 /* 0302 * This function opens the descriptor to hold an existing native descriptor. 0303 * 0304 * @param native_descriptor A native descriptor. 0305 * 0306 * @param ec Set to indicate what error occurred, if any. 0307 */ 0308 BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& native_descriptor, 0309 boost::system::error_code& ec) 0310 { 0311 impl_.get_service().assign( 0312 impl_.get_implementation(), native_descriptor, ec); 0313 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 0314 } 0315 0316 /// Determine whether the descriptor is open. 0317 bool is_open() const 0318 { 0319 return impl_.get_service().is_open(impl_.get_implementation()); 0320 } 0321 0322 /// Close the descriptor. 0323 /** 0324 * This function is used to close the descriptor. Any asynchronous read or 0325 * write operations will be cancelled immediately, and will complete with the 0326 * boost::asio::error::operation_aborted error. 0327 * 0328 * @throws boost::system::system_error Thrown on failure. Note that, even if 0329 * the function indicates an error, the underlying descriptor is closed. 0330 */ 0331 void close() 0332 { 0333 boost::system::error_code ec; 0334 impl_.get_service().close(impl_.get_implementation(), ec); 0335 boost::asio::detail::throw_error(ec, "close"); 0336 } 0337 0338 /// Close the descriptor. 0339 /** 0340 * This function is used to close the descriptor. Any asynchronous read or 0341 * write operations will be cancelled immediately, and will complete with the 0342 * boost::asio::error::operation_aborted error. 0343 * 0344 * @param ec Set to indicate what error occurred, if any. Note that, even if 0345 * the function indicates an error, the underlying descriptor is closed. 0346 */ 0347 BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) 0348 { 0349 impl_.get_service().close(impl_.get_implementation(), ec); 0350 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 0351 } 0352 0353 /// Get the native descriptor representation. 0354 /** 0355 * This function may be used to obtain the underlying representation of the 0356 * descriptor. This is intended to allow access to native descriptor 0357 * functionality that is not otherwise provided. 0358 */ 0359 native_handle_type native_handle() 0360 { 0361 return impl_.get_service().native_handle(impl_.get_implementation()); 0362 } 0363 0364 /// Release ownership of the native descriptor implementation. 0365 /** 0366 * This function may be used to obtain the underlying representation of the 0367 * descriptor. After calling this function, @c is_open() returns false. The 0368 * caller is responsible for closing the descriptor. 0369 * 0370 * All outstanding asynchronous read or write operations will finish 0371 * immediately, and the handlers for cancelled operations will be passed the 0372 * boost::asio::error::operation_aborted error. 0373 */ 0374 native_handle_type release() 0375 { 0376 return impl_.get_service().release(impl_.get_implementation()); 0377 } 0378 0379 /// Cancel all asynchronous operations associated with the descriptor. 0380 /** 0381 * This function causes all outstanding asynchronous read or write operations 0382 * to finish immediately, and the handlers for cancelled operations will be 0383 * passed the boost::asio::error::operation_aborted error. 0384 * 0385 * @throws boost::system::system_error Thrown on failure. 0386 */ 0387 void cancel() 0388 { 0389 boost::system::error_code ec; 0390 impl_.get_service().cancel(impl_.get_implementation(), ec); 0391 boost::asio::detail::throw_error(ec, "cancel"); 0392 } 0393 0394 /// Cancel all asynchronous operations associated with the descriptor. 0395 /** 0396 * This function causes all outstanding asynchronous read or write operations 0397 * to finish immediately, and the handlers for cancelled operations will be 0398 * passed the boost::asio::error::operation_aborted error. 0399 * 0400 * @param ec Set to indicate what error occurred, if any. 0401 */ 0402 BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) 0403 { 0404 impl_.get_service().cancel(impl_.get_implementation(), ec); 0405 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 0406 } 0407 0408 /// Perform an IO control command on the descriptor. 0409 /** 0410 * This function is used to execute an IO control command on the descriptor. 0411 * 0412 * @param command The IO control command to be performed on the descriptor. 0413 * 0414 * @throws boost::system::system_error Thrown on failure. 0415 * 0416 * @sa IoControlCommand @n 0417 * boost::asio::posix::descriptor_base::bytes_readable @n 0418 * boost::asio::posix::descriptor_base::non_blocking_io 0419 * 0420 * @par Example 0421 * Getting the number of bytes ready to read: 0422 * @code 0423 * boost::asio::posix::stream_descriptor descriptor(my_context); 0424 * ... 0425 * boost::asio::posix::stream_descriptor::bytes_readable command; 0426 * descriptor.io_control(command); 0427 * std::size_t bytes_readable = command.get(); 0428 * @endcode 0429 */ 0430 template <typename IoControlCommand> 0431 void io_control(IoControlCommand& command) 0432 { 0433 boost::system::error_code ec; 0434 impl_.get_service().io_control(impl_.get_implementation(), command, ec); 0435 boost::asio::detail::throw_error(ec, "io_control"); 0436 } 0437 0438 /// Perform an IO control command on the descriptor. 0439 /** 0440 * This function is used to execute an IO control command on the descriptor. 0441 * 0442 * @param command The IO control command to be performed on the descriptor. 0443 * 0444 * @param ec Set to indicate what error occurred, if any. 0445 * 0446 * @sa IoControlCommand @n 0447 * boost::asio::posix::descriptor_base::bytes_readable @n 0448 * boost::asio::posix::descriptor_base::non_blocking_io 0449 * 0450 * @par Example 0451 * Getting the number of bytes ready to read: 0452 * @code 0453 * boost::asio::posix::stream_descriptor descriptor(my_context); 0454 * ... 0455 * boost::asio::posix::stream_descriptor::bytes_readable command; 0456 * boost::system::error_code ec; 0457 * descriptor.io_control(command, ec); 0458 * if (ec) 0459 * { 0460 * // An error occurred. 0461 * } 0462 * std::size_t bytes_readable = command.get(); 0463 * @endcode 0464 */ 0465 template <typename IoControlCommand> 0466 BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command, 0467 boost::system::error_code& ec) 0468 { 0469 impl_.get_service().io_control(impl_.get_implementation(), command, ec); 0470 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 0471 } 0472 0473 /// Gets the non-blocking mode of the descriptor. 0474 /** 0475 * @returns @c true if the descriptor's synchronous operations will fail with 0476 * boost::asio::error::would_block if they are unable to perform the requested 0477 * operation immediately. If @c false, synchronous operations will block 0478 * until complete. 0479 * 0480 * @note The non-blocking mode has no effect on the behaviour of asynchronous 0481 * operations. Asynchronous operations will never fail with the error 0482 * boost::asio::error::would_block. 0483 */ 0484 bool non_blocking() const 0485 { 0486 return impl_.get_service().non_blocking(impl_.get_implementation()); 0487 } 0488 0489 /// Sets the non-blocking mode of the descriptor. 0490 /** 0491 * @param mode If @c true, the descriptor's synchronous operations will fail 0492 * with boost::asio::error::would_block if they are unable to perform the 0493 * requested operation immediately. If @c false, synchronous operations will 0494 * block until complete. 0495 * 0496 * @throws boost::system::system_error Thrown on failure. 0497 * 0498 * @note The non-blocking mode has no effect on the behaviour of asynchronous 0499 * operations. Asynchronous operations will never fail with the error 0500 * boost::asio::error::would_block. 0501 */ 0502 void non_blocking(bool mode) 0503 { 0504 boost::system::error_code ec; 0505 impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); 0506 boost::asio::detail::throw_error(ec, "non_blocking"); 0507 } 0508 0509 /// Sets the non-blocking mode of the descriptor. 0510 /** 0511 * @param mode If @c true, the descriptor's synchronous operations will fail 0512 * with boost::asio::error::would_block if they are unable to perform the 0513 * requested operation immediately. If @c false, synchronous operations will 0514 * block until complete. 0515 * 0516 * @param ec Set to indicate what error occurred, if any. 0517 * 0518 * @note The non-blocking mode has no effect on the behaviour of asynchronous 0519 * operations. Asynchronous operations will never fail with the error 0520 * boost::asio::error::would_block. 0521 */ 0522 BOOST_ASIO_SYNC_OP_VOID non_blocking( 0523 bool mode, boost::system::error_code& ec) 0524 { 0525 impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); 0526 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 0527 } 0528 0529 /// Gets the non-blocking mode of the native descriptor implementation. 0530 /** 0531 * This function is used to retrieve the non-blocking mode of the underlying 0532 * native descriptor. This mode has no effect on the behaviour of the 0533 * descriptor object's synchronous operations. 0534 * 0535 * @returns @c true if the underlying descriptor is in non-blocking mode and 0536 * direct system calls may fail with boost::asio::error::would_block (or the 0537 * equivalent system error). 0538 * 0539 * @note The current non-blocking mode is cached by the descriptor object. 0540 * Consequently, the return value may be incorrect if the non-blocking mode 0541 * was set directly on the native descriptor. 0542 */ 0543 bool native_non_blocking() const 0544 { 0545 return impl_.get_service().native_non_blocking( 0546 impl_.get_implementation()); 0547 } 0548 0549 /// Sets the non-blocking mode of the native descriptor implementation. 0550 /** 0551 * This function is used to modify the non-blocking mode of the underlying 0552 * native descriptor. It has no effect on the behaviour of the descriptor 0553 * object's synchronous operations. 0554 * 0555 * @param mode If @c true, the underlying descriptor is put into non-blocking 0556 * mode and direct system calls may fail with boost::asio::error::would_block 0557 * (or the equivalent system error). 0558 * 0559 * @throws boost::system::system_error Thrown on failure. If the @c mode is 0560 * @c false, but the current value of @c non_blocking() is @c true, this 0561 * function fails with boost::asio::error::invalid_argument, as the 0562 * combination does not make sense. 0563 */ 0564 void native_non_blocking(bool mode) 0565 { 0566 boost::system::error_code ec; 0567 impl_.get_service().native_non_blocking( 0568 impl_.get_implementation(), mode, ec); 0569 boost::asio::detail::throw_error(ec, "native_non_blocking"); 0570 } 0571 0572 /// Sets the non-blocking mode of the native descriptor implementation. 0573 /** 0574 * This function is used to modify the non-blocking mode of the underlying 0575 * native descriptor. It has no effect on the behaviour of the descriptor 0576 * object's synchronous operations. 0577 * 0578 * @param mode If @c true, the underlying descriptor is put into non-blocking 0579 * mode and direct system calls may fail with boost::asio::error::would_block 0580 * (or the equivalent system error). 0581 * 0582 * @param ec Set to indicate what error occurred, if any. If the @c mode is 0583 * @c false, but the current value of @c non_blocking() is @c true, this 0584 * function fails with boost::asio::error::invalid_argument, as the 0585 * combination does not make sense. 0586 */ 0587 BOOST_ASIO_SYNC_OP_VOID native_non_blocking( 0588 bool mode, boost::system::error_code& ec) 0589 { 0590 impl_.get_service().native_non_blocking( 0591 impl_.get_implementation(), mode, ec); 0592 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 0593 } 0594 0595 /// Wait for the descriptor to become ready to read, ready to write, or to 0596 /// have pending error conditions. 0597 /** 0598 * This function is used to perform a blocking wait for a descriptor to enter 0599 * a ready to read, write or error condition state. 0600 * 0601 * @param w Specifies the desired descriptor state. 0602 * 0603 * @par Example 0604 * Waiting for a descriptor to become readable. 0605 * @code 0606 * boost::asio::posix::stream_descriptor descriptor(my_context); 0607 * ... 0608 * descriptor.wait(boost::asio::posix::stream_descriptor::wait_read); 0609 * @endcode 0610 */ 0611 void wait(wait_type w) 0612 { 0613 boost::system::error_code ec; 0614 impl_.get_service().wait(impl_.get_implementation(), w, ec); 0615 boost::asio::detail::throw_error(ec, "wait"); 0616 } 0617 0618 /// Wait for the descriptor to become ready to read, ready to write, or to 0619 /// have pending error conditions. 0620 /** 0621 * This function is used to perform a blocking wait for a descriptor to enter 0622 * a ready to read, write or error condition state. 0623 * 0624 * @param w Specifies the desired descriptor state. 0625 * 0626 * @param ec Set to indicate what error occurred, if any. 0627 * 0628 * @par Example 0629 * Waiting for a descriptor to become readable. 0630 * @code 0631 * boost::asio::posix::stream_descriptor descriptor(my_context); 0632 * ... 0633 * boost::system::error_code ec; 0634 * descriptor.wait(boost::asio::posix::stream_descriptor::wait_read, ec); 0635 * @endcode 0636 */ 0637 BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec) 0638 { 0639 impl_.get_service().wait(impl_.get_implementation(), w, ec); 0640 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 0641 } 0642 0643 /// Asynchronously wait for the descriptor to become ready to read, ready to 0644 /// write, or to have pending error conditions. 0645 /** 0646 * This function is used to perform an asynchronous wait for a descriptor to 0647 * enter a ready to read, write or error condition state. It is an initiating 0648 * function for an @ref asynchronous_operation, and always returns 0649 * immediately. 0650 * 0651 * @param w Specifies the desired descriptor state. 0652 * 0653 * @param token The @ref completion_token that will be used to produce a 0654 * completion handler, which will be called when the wait completes. 0655 * Potential completion tokens include @ref use_future, @ref use_awaitable, 0656 * @ref yield_context, or a function object with the correct completion 0657 * signature. The function signature of the completion handler must be: 0658 * @code void handler( 0659 * const boost::system::error_code& error // Result of operation. 0660 * ); @endcode 0661 * Regardless of whether the asynchronous operation completes immediately or 0662 * not, the completion handler will not be invoked from within this function. 0663 * On immediate completion, invocation of the handler will be performed in a 0664 * manner equivalent to using boost::asio::post(). 0665 * 0666 * @par Completion Signature 0667 * @code void(boost::system::error_code) @endcode 0668 * 0669 * @par Example 0670 * @code 0671 * void wait_handler(const boost::system::error_code& error) 0672 * { 0673 * if (!error) 0674 * { 0675 * // Wait succeeded. 0676 * } 0677 * } 0678 * 0679 * ... 0680 * 0681 * boost::asio::posix::stream_descriptor descriptor(my_context); 0682 * ... 0683 * descriptor.async_wait( 0684 * boost::asio::posix::stream_descriptor::wait_read, 0685 * wait_handler); 0686 * @endcode 0687 * 0688 * @par Per-Operation Cancellation 0689 * This asynchronous operation supports cancellation for the following 0690 * boost::asio::cancellation_type values: 0691 * 0692 * @li @c cancellation_type::terminal 0693 * 0694 * @li @c cancellation_type::partial 0695 * 0696 * @li @c cancellation_type::total 0697 */ 0698 template < 0699 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code)) 0700 WaitToken = default_completion_token_t<executor_type>> 0701 auto async_wait(wait_type w, 0702 WaitToken&& token = default_completion_token_t<executor_type>()) 0703 -> decltype( 0704 async_initiate<WaitToken, void (boost::system::error_code)>( 0705 declval<initiate_async_wait>(), token, w)) 0706 { 0707 return async_initiate<WaitToken, void (boost::system::error_code)>( 0708 initiate_async_wait(this), token, w); 0709 } 0710 0711 protected: 0712 /// Protected destructor to prevent deletion through this type. 0713 /** 0714 * This function destroys the descriptor, cancelling any outstanding 0715 * asynchronous wait operations associated with the descriptor as if by 0716 * calling @c cancel. 0717 */ 0718 ~basic_descriptor() 0719 { 0720 } 0721 0722 #if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT) 0723 detail::io_object_impl<detail::io_uring_descriptor_service, Executor> impl_; 0724 #else // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT) 0725 detail::io_object_impl<detail::reactive_descriptor_service, Executor> impl_; 0726 #endif // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT) 0727 0728 private: 0729 // Disallow copying and assignment. 0730 basic_descriptor(const basic_descriptor&) = delete; 0731 basic_descriptor& operator=(const basic_descriptor&) = delete; 0732 0733 class initiate_async_wait 0734 { 0735 public: 0736 typedef Executor executor_type; 0737 0738 explicit initiate_async_wait(basic_descriptor* self) 0739 : self_(self) 0740 { 0741 } 0742 0743 const executor_type& get_executor() const noexcept 0744 { 0745 return self_->get_executor(); 0746 } 0747 0748 template <typename WaitHandler> 0749 void operator()(WaitHandler&& handler, wait_type w) const 0750 { 0751 // If you get an error on the following line it means that your handler 0752 // does not meet the documented type requirements for a WaitHandler. 0753 BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; 0754 0755 detail::non_const_lvalue<WaitHandler> handler2(handler); 0756 self_->impl_.get_service().async_wait( 0757 self_->impl_.get_implementation(), w, 0758 handler2.value, self_->impl_.get_executor()); 0759 } 0760 0761 private: 0762 basic_descriptor* self_; 0763 }; 0764 }; 0765 0766 } // namespace posix 0767 } // namespace asio 0768 } // namespace boost 0769 0770 #include <boost/asio/detail/pop_options.hpp> 0771 0772 #endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) 0773 // || defined(GENERATING_DOCUMENTATION) 0774 0775 #endif // BOOST_ASIO_POSIX_BASIC_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 |