1 // 2 // posix/basic_descriptor.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 // 7 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 // 10 11 #ifndef BOOST_ASIO_POSIX_BASIC_DESCRIPTOR_HPP 12 #define BOOST_ASIO_POSIX_BASIC_DESCRIPTOR_HPP 13 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 15 # pragma once 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18 #include <boost/asio/detail/config.hpp> 19 20 #if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \ 21 || defined(GENERATING_DOCUMENTATION) 22 23 #include <boost/asio/any_io_executor.hpp> 24 #include <boost/asio/async_result.hpp> 25 #include <boost/asio/detail/handler_type_requirements.hpp> 26 #include <boost/asio/detail/io_object_impl.hpp> 27 #include <boost/asio/detail/non_const_lvalue.hpp> 28 #include <boost/asio/detail/reactive_descriptor_service.hpp> 29 #include <boost/asio/detail/throw_error.hpp> 30 #include <boost/asio/error.hpp> 31 #include <boost/asio/execution_context.hpp> 32 #include <boost/asio/posix/descriptor_base.hpp> 33 34 #if defined(BOOST_ASIO_HAS_MOVE) 35 # include <utility> 36 #endif // defined(BOOST_ASIO_HAS_MOVE) 37 38 #include <boost/asio/detail/push_options.hpp> 39 40 namespace boost { 41 namespace asio { 42 namespace posix { 43 44 /// Provides POSIX descriptor functionality. 45 /** 46 * The posix::basic_descriptor class template provides the ability to wrap a 47 * POSIX descriptor. 48 * 49 * @par Thread Safety 50 * @e Distinct @e objects: Safe.@n 51 * @e Shared @e objects: Unsafe. 52 */ 53 template <typename Executor = any_io_executor> 54 class basic_descriptor 55 : public descriptor_base 56 { 57 public: 58 /// The type of the executor associated with the object. 59 typedef Executor executor_type; 60 61 /// Rebinds the descriptor type to another executor. 62 template <typename Executor1> 63 struct rebind_executor 64 { 65 /// The descriptor type when rebound to the specified executor. 66 typedef basic_descriptor<Executor1> other; 67 }; 68 69 /// The native representation of a descriptor. 70 #if defined(GENERATING_DOCUMENTATION) 71 typedef implementation_defined native_handle_type; 72 #else 73 typedef detail::reactive_descriptor_service::native_handle_type 74 native_handle_type; 75 #endif 76 77 /// A descriptor is always the lowest layer. 78 typedef basic_descriptor lowest_layer_type; 79 80 /// Construct a descriptor without opening it. 81 /** 82 * This constructor creates a descriptor without opening it. 83 * 84 * @param ex The I/O executor that the descriptor will use, by default, to 85 * dispatch handlers for any asynchronous operations performed on the 86 * descriptor. 87 */ basic_descriptor(const executor_type & ex)88 explicit basic_descriptor(const executor_type& ex) 89 : impl_(0, ex) 90 { 91 } 92 93 /// Construct a descriptor without opening it. 94 /** 95 * This constructor creates a descriptor without opening it. 96 * 97 * @param context An execution context which provides the I/O executor that 98 * the descriptor will use, by default, to dispatch handlers for any 99 * asynchronous operations performed on the descriptor. 100 */ 101 template <typename ExecutionContext> basic_descriptor(ExecutionContext & context,typename constraint<is_convertible<ExecutionContext &,execution_context &>::value,defaulted_constraint>::type=defaulted_constraint ())102 explicit basic_descriptor(ExecutionContext& context, 103 typename constraint< 104 is_convertible<ExecutionContext&, execution_context&>::value, 105 defaulted_constraint 106 >::type = defaulted_constraint()) 107 : impl_(0, 0, context) 108 { 109 } 110 111 /// Construct a descriptor on an existing native descriptor. 112 /** 113 * This constructor creates a descriptor object to hold an existing native 114 * descriptor. 115 * 116 * @param ex The I/O executor that the descriptor will use, by default, to 117 * dispatch handlers for any asynchronous operations performed on the 118 * descriptor. 119 * 120 * @param native_descriptor A native descriptor. 121 * 122 * @throws boost::system::system_error Thrown on failure. 123 */ basic_descriptor(const executor_type & ex,const native_handle_type & native_descriptor)124 basic_descriptor(const executor_type& ex, 125 const native_handle_type& native_descriptor) 126 : impl_(0, ex) 127 { 128 boost::system::error_code ec; 129 impl_.get_service().assign(impl_.get_implementation(), 130 native_descriptor, ec); 131 boost::asio::detail::throw_error(ec, "assign"); 132 } 133 134 /// Construct a descriptor on an existing native descriptor. 135 /** 136 * This constructor creates a descriptor object to hold an existing native 137 * descriptor. 138 * 139 * @param context An execution context which provides the I/O executor that 140 * the descriptor will use, by default, to dispatch handlers for any 141 * asynchronous operations performed on the descriptor. 142 * 143 * @param native_descriptor A native descriptor. 144 * 145 * @throws boost::system::system_error Thrown on failure. 146 */ 147 template <typename ExecutionContext> basic_descriptor(ExecutionContext & context,const native_handle_type & native_descriptor,typename constraint<is_convertible<ExecutionContext &,execution_context &>::value>::type=0)148 basic_descriptor(ExecutionContext& context, 149 const native_handle_type& native_descriptor, 150 typename constraint< 151 is_convertible<ExecutionContext&, execution_context&>::value 152 >::type = 0) 153 : impl_(0, 0, context) 154 { 155 boost::system::error_code ec; 156 impl_.get_service().assign(impl_.get_implementation(), 157 native_descriptor, ec); 158 boost::asio::detail::throw_error(ec, "assign"); 159 } 160 161 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 162 /// Move-construct a descriptor from another. 163 /** 164 * This constructor moves a descriptor from one object to another. 165 * 166 * @param other The other descriptor object from which the move will 167 * occur. 168 * 169 * @note Following the move, the moved-from object is in the same state as if 170 * constructed using the @c basic_descriptor(const executor_type&) 171 * constructor. 172 */ basic_descriptor(basic_descriptor && other)173 basic_descriptor(basic_descriptor&& other) BOOST_ASIO_NOEXCEPT 174 : impl_(std::move(other.impl_)) 175 { 176 } 177 178 /// Move-assign a descriptor from another. 179 /** 180 * This assignment operator moves a descriptor from one object to another. 181 * 182 * @param other The other descriptor object from which the move will 183 * occur. 184 * 185 * @note Following the move, the moved-from object is in the same state as if 186 * constructed using the @c basic_descriptor(const executor_type&) 187 * constructor. 188 */ operator =(basic_descriptor && other)189 basic_descriptor& operator=(basic_descriptor&& other) 190 { 191 impl_ = std::move(other.impl_); 192 return *this; 193 } 194 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 195 196 /// Get the executor associated with the object. get_executor()197 executor_type get_executor() BOOST_ASIO_NOEXCEPT 198 { 199 return impl_.get_executor(); 200 } 201 202 /// Get a reference to the lowest layer. 203 /** 204 * This function returns a reference to the lowest layer in a stack of 205 * layers. Since a descriptor cannot contain any further layers, it 206 * simply returns a reference to itself. 207 * 208 * @return A reference to the lowest layer in the stack of layers. Ownership 209 * is not transferred to the caller. 210 */ lowest_layer()211 lowest_layer_type& lowest_layer() 212 { 213 return *this; 214 } 215 216 /// Get a const reference to the lowest layer. 217 /** 218 * This function returns a const reference to the lowest layer in a stack of 219 * layers. Since a descriptor cannot contain any further layers, it 220 * simply returns a reference to itself. 221 * 222 * @return A const reference to the lowest layer in the stack of layers. 223 * Ownership is not transferred to the caller. 224 */ lowest_layer() const225 const lowest_layer_type& lowest_layer() const 226 { 227 return *this; 228 } 229 230 /// Assign an existing native descriptor to the descriptor. 231 /* 232 * This function opens the descriptor to hold an existing native descriptor. 233 * 234 * @param native_descriptor A native descriptor. 235 * 236 * @throws boost::system::system_error Thrown on failure. 237 */ assign(const native_handle_type & native_descriptor)238 void assign(const native_handle_type& native_descriptor) 239 { 240 boost::system::error_code ec; 241 impl_.get_service().assign(impl_.get_implementation(), 242 native_descriptor, ec); 243 boost::asio::detail::throw_error(ec, "assign"); 244 } 245 246 /// Assign an existing native descriptor to the descriptor. 247 /* 248 * This function opens the descriptor to hold an existing native descriptor. 249 * 250 * @param native_descriptor A native descriptor. 251 * 252 * @param ec Set to indicate what error occurred, if any. 253 */ assign(const native_handle_type & native_descriptor,boost::system::error_code & ec)254 BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& native_descriptor, 255 boost::system::error_code& ec) 256 { 257 impl_.get_service().assign( 258 impl_.get_implementation(), native_descriptor, ec); 259 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 260 } 261 262 /// Determine whether the descriptor is open. is_open() const263 bool is_open() const 264 { 265 return impl_.get_service().is_open(impl_.get_implementation()); 266 } 267 268 /// Close the descriptor. 269 /** 270 * This function is used to close the descriptor. Any asynchronous read or 271 * write operations will be cancelled immediately, and will complete with the 272 * boost::asio::error::operation_aborted error. 273 * 274 * @throws boost::system::system_error Thrown on failure. Note that, even if 275 * the function indicates an error, the underlying descriptor is closed. 276 */ close()277 void close() 278 { 279 boost::system::error_code ec; 280 impl_.get_service().close(impl_.get_implementation(), ec); 281 boost::asio::detail::throw_error(ec, "close"); 282 } 283 284 /// Close the descriptor. 285 /** 286 * This function is used to close the descriptor. Any asynchronous read or 287 * write operations will be cancelled immediately, and will complete with the 288 * boost::asio::error::operation_aborted error. 289 * 290 * @param ec Set to indicate what error occurred, if any. Note that, even if 291 * the function indicates an error, the underlying descriptor is closed. 292 */ close(boost::system::error_code & ec)293 BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) 294 { 295 impl_.get_service().close(impl_.get_implementation(), ec); 296 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 297 } 298 299 /// Get the native descriptor representation. 300 /** 301 * This function may be used to obtain the underlying representation of the 302 * descriptor. This is intended to allow access to native descriptor 303 * functionality that is not otherwise provided. 304 */ native_handle()305 native_handle_type native_handle() 306 { 307 return impl_.get_service().native_handle(impl_.get_implementation()); 308 } 309 310 /// Release ownership of the native descriptor implementation. 311 /** 312 * This function may be used to obtain the underlying representation of the 313 * descriptor. After calling this function, @c is_open() returns false. The 314 * caller is responsible for closing the descriptor. 315 * 316 * All outstanding asynchronous read or write operations will finish 317 * immediately, and the handlers for cancelled operations will be passed the 318 * boost::asio::error::operation_aborted error. 319 */ release()320 native_handle_type release() 321 { 322 return impl_.get_service().release(impl_.get_implementation()); 323 } 324 325 /// Cancel all asynchronous operations associated with the descriptor. 326 /** 327 * This function causes all outstanding asynchronous read or write operations 328 * to finish immediately, and the handlers for cancelled operations will be 329 * passed the boost::asio::error::operation_aborted error. 330 * 331 * @throws boost::system::system_error Thrown on failure. 332 */ cancel()333 void cancel() 334 { 335 boost::system::error_code ec; 336 impl_.get_service().cancel(impl_.get_implementation(), ec); 337 boost::asio::detail::throw_error(ec, "cancel"); 338 } 339 340 /// Cancel all asynchronous operations associated with the descriptor. 341 /** 342 * This function causes all outstanding asynchronous read or write operations 343 * to finish immediately, and the handlers for cancelled operations will be 344 * passed the boost::asio::error::operation_aborted error. 345 * 346 * @param ec Set to indicate what error occurred, if any. 347 */ cancel(boost::system::error_code & ec)348 BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) 349 { 350 impl_.get_service().cancel(impl_.get_implementation(), ec); 351 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 352 } 353 354 /// Perform an IO control command on the descriptor. 355 /** 356 * This function is used to execute an IO control command on the descriptor. 357 * 358 * @param command The IO control command to be performed on the descriptor. 359 * 360 * @throws boost::system::system_error Thrown on failure. 361 * 362 * @sa IoControlCommand @n 363 * boost::asio::posix::descriptor_base::bytes_readable @n 364 * boost::asio::posix::descriptor_base::non_blocking_io 365 * 366 * @par Example 367 * Getting the number of bytes ready to read: 368 * @code 369 * boost::asio::posix::stream_descriptor descriptor(my_context); 370 * ... 371 * boost::asio::posix::stream_descriptor::bytes_readable command; 372 * descriptor.io_control(command); 373 * std::size_t bytes_readable = command.get(); 374 * @endcode 375 */ 376 template <typename IoControlCommand> io_control(IoControlCommand & command)377 void io_control(IoControlCommand& command) 378 { 379 boost::system::error_code ec; 380 impl_.get_service().io_control(impl_.get_implementation(), command, ec); 381 boost::asio::detail::throw_error(ec, "io_control"); 382 } 383 384 /// Perform an IO control command on the descriptor. 385 /** 386 * This function is used to execute an IO control command on the descriptor. 387 * 388 * @param command The IO control command to be performed on the descriptor. 389 * 390 * @param ec Set to indicate what error occurred, if any. 391 * 392 * @sa IoControlCommand @n 393 * boost::asio::posix::descriptor_base::bytes_readable @n 394 * boost::asio::posix::descriptor_base::non_blocking_io 395 * 396 * @par Example 397 * Getting the number of bytes ready to read: 398 * @code 399 * boost::asio::posix::stream_descriptor descriptor(my_context); 400 * ... 401 * boost::asio::posix::stream_descriptor::bytes_readable command; 402 * boost::system::error_code ec; 403 * descriptor.io_control(command, ec); 404 * if (ec) 405 * { 406 * // An error occurred. 407 * } 408 * std::size_t bytes_readable = command.get(); 409 * @endcode 410 */ 411 template <typename IoControlCommand> io_control(IoControlCommand & command,boost::system::error_code & ec)412 BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command, 413 boost::system::error_code& ec) 414 { 415 impl_.get_service().io_control(impl_.get_implementation(), command, ec); 416 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 417 } 418 419 /// Gets the non-blocking mode of the descriptor. 420 /** 421 * @returns @c true if the descriptor's synchronous operations will fail with 422 * boost::asio::error::would_block if they are unable to perform the requested 423 * operation immediately. If @c false, synchronous operations will block 424 * until complete. 425 * 426 * @note The non-blocking mode has no effect on the behaviour of asynchronous 427 * operations. Asynchronous operations will never fail with the error 428 * boost::asio::error::would_block. 429 */ non_blocking() const430 bool non_blocking() const 431 { 432 return impl_.get_service().non_blocking(impl_.get_implementation()); 433 } 434 435 /// Sets the non-blocking mode of the descriptor. 436 /** 437 * @param mode If @c true, the descriptor's synchronous operations will fail 438 * with boost::asio::error::would_block if they are unable to perform the 439 * requested operation immediately. If @c false, synchronous operations will 440 * block until complete. 441 * 442 * @throws boost::system::system_error Thrown on failure. 443 * 444 * @note The non-blocking mode has no effect on the behaviour of asynchronous 445 * operations. Asynchronous operations will never fail with the error 446 * boost::asio::error::would_block. 447 */ non_blocking(bool mode)448 void non_blocking(bool mode) 449 { 450 boost::system::error_code ec; 451 impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); 452 boost::asio::detail::throw_error(ec, "non_blocking"); 453 } 454 455 /// Sets the non-blocking mode of the descriptor. 456 /** 457 * @param mode If @c true, the descriptor's synchronous operations will fail 458 * with boost::asio::error::would_block if they are unable to perform the 459 * requested operation immediately. If @c false, synchronous operations will 460 * block until complete. 461 * 462 * @param ec Set to indicate what error occurred, if any. 463 * 464 * @note The non-blocking mode has no effect on the behaviour of asynchronous 465 * operations. Asynchronous operations will never fail with the error 466 * boost::asio::error::would_block. 467 */ non_blocking(bool mode,boost::system::error_code & ec)468 BOOST_ASIO_SYNC_OP_VOID non_blocking( 469 bool mode, boost::system::error_code& ec) 470 { 471 impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); 472 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 473 } 474 475 /// Gets the non-blocking mode of the native descriptor implementation. 476 /** 477 * This function is used to retrieve the non-blocking mode of the underlying 478 * native descriptor. This mode has no effect on the behaviour of the 479 * descriptor object's synchronous operations. 480 * 481 * @returns @c true if the underlying descriptor is in non-blocking mode and 482 * direct system calls may fail with boost::asio::error::would_block (or the 483 * equivalent system error). 484 * 485 * @note The current non-blocking mode is cached by the descriptor object. 486 * Consequently, the return value may be incorrect if the non-blocking mode 487 * was set directly on the native descriptor. 488 */ native_non_blocking() const489 bool native_non_blocking() const 490 { 491 return impl_.get_service().native_non_blocking( 492 impl_.get_implementation()); 493 } 494 495 /// Sets the non-blocking mode of the native descriptor implementation. 496 /** 497 * This function is used to modify the non-blocking mode of the underlying 498 * native descriptor. It has no effect on the behaviour of the descriptor 499 * object's synchronous operations. 500 * 501 * @param mode If @c true, the underlying descriptor is put into non-blocking 502 * mode and direct system calls may fail with boost::asio::error::would_block 503 * (or the equivalent system error). 504 * 505 * @throws boost::system::system_error Thrown on failure. If the @c mode is 506 * @c false, but the current value of @c non_blocking() is @c true, this 507 * function fails with boost::asio::error::invalid_argument, as the 508 * combination does not make sense. 509 */ native_non_blocking(bool mode)510 void native_non_blocking(bool mode) 511 { 512 boost::system::error_code ec; 513 impl_.get_service().native_non_blocking( 514 impl_.get_implementation(), mode, ec); 515 boost::asio::detail::throw_error(ec, "native_non_blocking"); 516 } 517 518 /// Sets the non-blocking mode of the native descriptor implementation. 519 /** 520 * This function is used to modify the non-blocking mode of the underlying 521 * native descriptor. It has no effect on the behaviour of the descriptor 522 * object's synchronous operations. 523 * 524 * @param mode If @c true, the underlying descriptor is put into non-blocking 525 * mode and direct system calls may fail with boost::asio::error::would_block 526 * (or the equivalent system error). 527 * 528 * @param ec Set to indicate what error occurred, if any. If the @c mode is 529 * @c false, but the current value of @c non_blocking() is @c true, this 530 * function fails with boost::asio::error::invalid_argument, as the 531 * combination does not make sense. 532 */ native_non_blocking(bool mode,boost::system::error_code & ec)533 BOOST_ASIO_SYNC_OP_VOID native_non_blocking( 534 bool mode, boost::system::error_code& ec) 535 { 536 impl_.get_service().native_non_blocking( 537 impl_.get_implementation(), mode, ec); 538 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 539 } 540 541 /// Wait for the descriptor to become ready to read, ready to write, or to 542 /// have pending error conditions. 543 /** 544 * This function is used to perform a blocking wait for a descriptor to enter 545 * a ready to read, write or error condition state. 546 * 547 * @param w Specifies the desired descriptor state. 548 * 549 * @par Example 550 * Waiting for a descriptor to become readable. 551 * @code 552 * boost::asio::posix::stream_descriptor descriptor(my_context); 553 * ... 554 * descriptor.wait(boost::asio::posix::stream_descriptor::wait_read); 555 * @endcode 556 */ wait(wait_type w)557 void wait(wait_type w) 558 { 559 boost::system::error_code ec; 560 impl_.get_service().wait(impl_.get_implementation(), w, ec); 561 boost::asio::detail::throw_error(ec, "wait"); 562 } 563 564 /// Wait for the descriptor to become ready to read, ready to write, or to 565 /// have pending error conditions. 566 /** 567 * This function is used to perform a blocking wait for a descriptor to enter 568 * a ready to read, write or error condition state. 569 * 570 * @param w Specifies the desired descriptor state. 571 * 572 * @param ec Set to indicate what error occurred, if any. 573 * 574 * @par Example 575 * Waiting for a descriptor to become readable. 576 * @code 577 * boost::asio::posix::stream_descriptor descriptor(my_context); 578 * ... 579 * boost::system::error_code ec; 580 * descriptor.wait(boost::asio::posix::stream_descriptor::wait_read, ec); 581 * @endcode 582 */ wait(wait_type w,boost::system::error_code & ec)583 BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec) 584 { 585 impl_.get_service().wait(impl_.get_implementation(), w, ec); 586 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 587 } 588 589 /// Asynchronously wait for the descriptor to become ready to read, ready to 590 /// write, or to have pending error conditions. 591 /** 592 * This function is used to perform an asynchronous wait for a descriptor to 593 * enter a ready to read, write or error condition state. 594 * 595 * @param w Specifies the desired descriptor state. 596 * 597 * @param handler The handler to be called when the wait operation completes. 598 * Copies will be made of the handler as required. The function signature of 599 * the handler must be: 600 * @code void handler( 601 * const boost::system::error_code& error // Result of operation 602 * ); @endcode 603 * Regardless of whether the asynchronous operation completes immediately or 604 * not, the handler will not be invoked from within this function. On 605 * immediate completion, invocation of the handler will be performed in a 606 * manner equivalent to using boost::asio::post(). 607 * 608 * @par Example 609 * @code 610 * void wait_handler(const boost::system::error_code& error) 611 * { 612 * if (!error) 613 * { 614 * // Wait succeeded. 615 * } 616 * } 617 * 618 * ... 619 * 620 * boost::asio::posix::stream_descriptor descriptor(my_context); 621 * ... 622 * descriptor.async_wait( 623 * boost::asio::posix::stream_descriptor::wait_read, 624 * wait_handler); 625 * @endcode 626 */ 627 template < 628 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code)) 629 WaitHandler BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,void (boost::system::error_code))630 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler, 631 void (boost::system::error_code)) 632 async_wait(wait_type w, 633 BOOST_ASIO_MOVE_ARG(WaitHandler) handler 634 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) 635 { 636 return async_initiate<WaitHandler, void (boost::system::error_code)>( 637 initiate_async_wait(this), handler, w); 638 } 639 640 protected: 641 /// Protected destructor to prevent deletion through this type. 642 /** 643 * This function destroys the descriptor, cancelling any outstanding 644 * asynchronous wait operations associated with the descriptor as if by 645 * calling @c cancel. 646 */ ~basic_descriptor()647 ~basic_descriptor() 648 { 649 } 650 651 detail::io_object_impl<detail::reactive_descriptor_service, Executor> impl_; 652 653 private: 654 // Disallow copying and assignment. 655 basic_descriptor(const basic_descriptor&) BOOST_ASIO_DELETED; 656 basic_descriptor& operator=(const basic_descriptor&) BOOST_ASIO_DELETED; 657 658 class initiate_async_wait 659 { 660 public: 661 typedef Executor executor_type; 662 initiate_async_wait(basic_descriptor * self)663 explicit initiate_async_wait(basic_descriptor* self) 664 : self_(self) 665 { 666 } 667 get_executor() const668 executor_type get_executor() const BOOST_ASIO_NOEXCEPT 669 { 670 return self_->get_executor(); 671 } 672 673 template <typename WaitHandler> operator ()(BOOST_ASIO_MOVE_ARG (WaitHandler)handler,wait_type w) const674 void operator()(BOOST_ASIO_MOVE_ARG(WaitHandler) handler, wait_type w) const 675 { 676 // If you get an error on the following line it means that your handler 677 // does not meet the documented type requirements for a WaitHandler. 678 BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; 679 680 detail::non_const_lvalue<WaitHandler> handler2(handler); 681 self_->impl_.get_service().async_wait( 682 self_->impl_.get_implementation(), w, 683 handler2.value, self_->impl_.get_executor()); 684 } 685 686 private: 687 basic_descriptor* self_; 688 }; 689 }; 690 691 } // namespace posix 692 } // namespace asio 693 } // namespace boost 694 695 #include <boost/asio/detail/pop_options.hpp> 696 697 #endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) 698 // || defined(GENERATING_DOCUMENTATION) 699 700 #endif // BOOST_ASIO_POSIX_BASIC_DESCRIPTOR_HPP 701