2 // posix/basic_descriptor.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #ifndef BOOST_ASIO_POSIX_BASIC_DESCRIPTOR_HPP
12 #define BOOST_ASIO_POSIX_BASIC_DESCRIPTOR_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/config.hpp>
20 #if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
21 || defined(GENERATING_DOCUMENTATION)
23 #include <boost/asio/async_result.hpp>
24 #include <boost/asio/detail/handler_type_requirements.hpp>
25 #include <boost/asio/detail/io_object_impl.hpp>
26 #include <boost/asio/detail/non_const_lvalue.hpp>
27 #include <boost/asio/detail/reactive_descriptor_service.hpp>
28 #include <boost/asio/detail/throw_error.hpp>
29 #include <boost/asio/error.hpp>
30 #include <boost/asio/execution_context.hpp>
31 #include <boost/asio/executor.hpp>
32 #include <boost/asio/posix/descriptor_base.hpp>
34 #if defined(BOOST_ASIO_HAS_MOVE)
36 #endif // defined(BOOST_ASIO_HAS_MOVE)
38 #include <boost/asio/detail/push_options.hpp>
44 /// Provides POSIX descriptor functionality.
46 * The posix::basic_descriptor class template provides the ability to wrap a
50 * @e Distinct @e objects: Safe.@n
51 * @e Shared @e objects: Unsafe.
53 template <typename Executor = executor>
54 class basic_descriptor
55 : public descriptor_base
58 /// The type of the executor associated with the object.
59 typedef Executor executor_type;
61 /// Rebinds the descriptor type to another executor.
62 template <typename Executor1>
63 struct rebind_executor
65 /// The descriptor type when rebound to the specified executor.
66 typedef basic_descriptor<Executor1> other;
69 /// The native representation of a descriptor.
70 #if defined(GENERATING_DOCUMENTATION)
71 typedef implementation_defined native_handle_type;
73 typedef detail::reactive_descriptor_service::native_handle_type
77 /// A descriptor is always the lowest layer.
78 typedef basic_descriptor lowest_layer_type;
80 /// Construct a descriptor without opening it.
82 * This constructor creates a descriptor without opening it.
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
88 explicit basic_descriptor(const executor_type& ex)
93 /// Construct a descriptor without opening it.
95 * This constructor creates a descriptor without opening it.
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.
101 template <typename ExecutionContext>
102 explicit basic_descriptor(ExecutionContext& context,
104 is_convertible<ExecutionContext&, execution_context&>::value
110 /// Construct a descriptor on an existing native descriptor.
112 * This constructor creates a descriptor object to hold an existing native
115 * @param ex The I/O executor that the descriptor will use, by default, to
116 * dispatch handlers for any asynchronous operations performed on the
119 * @param native_descriptor A native descriptor.
121 * @throws boost::system::system_error Thrown on failure.
123 basic_descriptor(const executor_type& ex,
124 const native_handle_type& native_descriptor)
127 boost::system::error_code ec;
128 impl_.get_service().assign(impl_.get_implementation(),
129 native_descriptor, ec);
130 boost::asio::detail::throw_error(ec, "assign");
133 /// Construct a descriptor on an existing native descriptor.
135 * This constructor creates a descriptor object to hold an existing native
138 * @param context An execution context which provides the I/O executor that
139 * the descriptor will use, by default, to dispatch handlers for any
140 * asynchronous operations performed on the descriptor.
142 * @param native_descriptor A native descriptor.
144 * @throws boost::system::system_error Thrown on failure.
146 template <typename ExecutionContext>
147 basic_descriptor(ExecutionContext& context,
148 const native_handle_type& native_descriptor,
150 is_convertible<ExecutionContext&, execution_context&>::value
154 boost::system::error_code ec;
155 impl_.get_service().assign(impl_.get_implementation(),
156 native_descriptor, ec);
157 boost::asio::detail::throw_error(ec, "assign");
160 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
161 /// Move-construct a descriptor from another.
163 * This constructor moves a descriptor from one object to another.
165 * @param other The other descriptor object from which the move will
168 * @note Following the move, the moved-from object is in the same state as if
169 * constructed using the @c basic_descriptor(const executor_type&)
172 basic_descriptor(basic_descriptor&& other)
173 : impl_(std::move(other.impl_))
177 /// Move-assign a descriptor from another.
179 * This assignment operator moves a descriptor from one object to another.
181 * @param other The other descriptor object from which the move will
184 * @note Following the move, the moved-from object is in the same state as if
185 * constructed using the @c basic_descriptor(const executor_type&)
188 basic_descriptor& operator=(basic_descriptor&& other)
190 impl_ = std::move(other.impl_);
193 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
195 /// Get the executor associated with the object.
196 executor_type get_executor() BOOST_ASIO_NOEXCEPT
198 return impl_.get_executor();
201 /// Get a reference to the lowest layer.
203 * This function returns a reference to the lowest layer in a stack of
204 * layers. Since a descriptor cannot contain any further layers, it
205 * simply returns a reference to itself.
207 * @return A reference to the lowest layer in the stack of layers. Ownership
208 * is not transferred to the caller.
210 lowest_layer_type& lowest_layer()
215 /// Get a const reference to the lowest layer.
217 * This function returns a const reference to the lowest layer in a stack of
218 * layers. Since a descriptor cannot contain any further layers, it
219 * simply returns a reference to itself.
221 * @return A const reference to the lowest layer in the stack of layers.
222 * Ownership is not transferred to the caller.
224 const lowest_layer_type& lowest_layer() const
229 /// Assign an existing native descriptor to the descriptor.
231 * This function opens the descriptor to hold an existing native descriptor.
233 * @param native_descriptor A native descriptor.
235 * @throws boost::system::system_error Thrown on failure.
237 void assign(const native_handle_type& native_descriptor)
239 boost::system::error_code ec;
240 impl_.get_service().assign(impl_.get_implementation(),
241 native_descriptor, ec);
242 boost::asio::detail::throw_error(ec, "assign");
245 /// Assign an existing native descriptor to the descriptor.
247 * This function opens the descriptor to hold an existing native descriptor.
249 * @param native_descriptor A native descriptor.
251 * @param ec Set to indicate what error occurred, if any.
253 BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& native_descriptor,
254 boost::system::error_code& ec)
256 impl_.get_service().assign(
257 impl_.get_implementation(), native_descriptor, ec);
258 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
261 /// Determine whether the descriptor is open.
264 return impl_.get_service().is_open(impl_.get_implementation());
267 /// Close the descriptor.
269 * This function is used to close the descriptor. Any asynchronous read or
270 * write operations will be cancelled immediately, and will complete with the
271 * boost::asio::error::operation_aborted error.
273 * @throws boost::system::system_error Thrown on failure. Note that, even if
274 * the function indicates an error, the underlying descriptor is closed.
278 boost::system::error_code ec;
279 impl_.get_service().close(impl_.get_implementation(), ec);
280 boost::asio::detail::throw_error(ec, "close");
283 /// Close the descriptor.
285 * This function is used to close the descriptor. Any asynchronous read or
286 * write operations will be cancelled immediately, and will complete with the
287 * boost::asio::error::operation_aborted error.
289 * @param ec Set to indicate what error occurred, if any. Note that, even if
290 * the function indicates an error, the underlying descriptor is closed.
292 BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
294 impl_.get_service().close(impl_.get_implementation(), ec);
295 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
298 /// Get the native descriptor representation.
300 * This function may be used to obtain the underlying representation of the
301 * descriptor. This is intended to allow access to native descriptor
302 * functionality that is not otherwise provided.
304 native_handle_type native_handle()
306 return impl_.get_service().native_handle(impl_.get_implementation());
309 /// Release ownership of the native descriptor implementation.
311 * This function may be used to obtain the underlying representation of the
312 * descriptor. After calling this function, @c is_open() returns false. The
313 * caller is responsible for closing the descriptor.
315 * All outstanding asynchronous read or write operations will finish
316 * immediately, and the handlers for cancelled operations will be passed the
317 * boost::asio::error::operation_aborted error.
319 native_handle_type release()
321 return impl_.get_service().release(impl_.get_implementation());
324 /// Cancel all asynchronous operations associated with the descriptor.
326 * This function causes all outstanding asynchronous read or write operations
327 * to finish immediately, and the handlers for cancelled operations will be
328 * passed the boost::asio::error::operation_aborted error.
330 * @throws boost::system::system_error Thrown on failure.
334 boost::system::error_code ec;
335 impl_.get_service().cancel(impl_.get_implementation(), ec);
336 boost::asio::detail::throw_error(ec, "cancel");
339 /// Cancel all asynchronous operations associated with the descriptor.
341 * This function causes all outstanding asynchronous read or write operations
342 * to finish immediately, and the handlers for cancelled operations will be
343 * passed the boost::asio::error::operation_aborted error.
345 * @param ec Set to indicate what error occurred, if any.
347 BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
349 impl_.get_service().cancel(impl_.get_implementation(), ec);
350 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
353 /// Perform an IO control command on the descriptor.
355 * This function is used to execute an IO control command on the descriptor.
357 * @param command The IO control command to be performed on the descriptor.
359 * @throws boost::system::system_error Thrown on failure.
361 * @sa IoControlCommand @n
362 * boost::asio::posix::descriptor_base::bytes_readable @n
363 * boost::asio::posix::descriptor_base::non_blocking_io
366 * Getting the number of bytes ready to read:
368 * boost::asio::posix::stream_descriptor descriptor(my_context);
370 * boost::asio::posix::stream_descriptor::bytes_readable command;
371 * descriptor.io_control(command);
372 * std::size_t bytes_readable = command.get();
375 template <typename IoControlCommand>
376 void io_control(IoControlCommand& command)
378 boost::system::error_code ec;
379 impl_.get_service().io_control(impl_.get_implementation(), command, ec);
380 boost::asio::detail::throw_error(ec, "io_control");
383 /// Perform an IO control command on the descriptor.
385 * This function is used to execute an IO control command on the descriptor.
387 * @param command The IO control command to be performed on the descriptor.
389 * @param ec Set to indicate what error occurred, if any.
391 * @sa IoControlCommand @n
392 * boost::asio::posix::descriptor_base::bytes_readable @n
393 * boost::asio::posix::descriptor_base::non_blocking_io
396 * Getting the number of bytes ready to read:
398 * boost::asio::posix::stream_descriptor descriptor(my_context);
400 * boost::asio::posix::stream_descriptor::bytes_readable command;
401 * boost::system::error_code ec;
402 * descriptor.io_control(command, ec);
405 * // An error occurred.
407 * std::size_t bytes_readable = command.get();
410 template <typename IoControlCommand>
411 BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command,
412 boost::system::error_code& ec)
414 impl_.get_service().io_control(impl_.get_implementation(), command, ec);
415 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
418 /// Gets the non-blocking mode of the descriptor.
420 * @returns @c true if the descriptor's synchronous operations will fail with
421 * boost::asio::error::would_block if they are unable to perform the requested
422 * operation immediately. If @c false, synchronous operations will block
425 * @note The non-blocking mode has no effect on the behaviour of asynchronous
426 * operations. Asynchronous operations will never fail with the error
427 * boost::asio::error::would_block.
429 bool non_blocking() const
431 return impl_.get_service().non_blocking(impl_.get_implementation());
434 /// Sets the non-blocking mode of the descriptor.
436 * @param mode If @c true, the descriptor's synchronous operations will fail
437 * with boost::asio::error::would_block if they are unable to perform the
438 * requested operation immediately. If @c false, synchronous operations will
439 * block until complete.
441 * @throws boost::system::system_error Thrown on failure.
443 * @note The non-blocking mode has no effect on the behaviour of asynchronous
444 * operations. Asynchronous operations will never fail with the error
445 * boost::asio::error::would_block.
447 void non_blocking(bool mode)
449 boost::system::error_code ec;
450 impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);
451 boost::asio::detail::throw_error(ec, "non_blocking");
454 /// Sets the non-blocking mode of the descriptor.
456 * @param mode If @c true, the descriptor's synchronous operations will fail
457 * with boost::asio::error::would_block if they are unable to perform the
458 * requested operation immediately. If @c false, synchronous operations will
459 * block until complete.
461 * @param ec Set to indicate what error occurred, if any.
463 * @note The non-blocking mode has no effect on the behaviour of asynchronous
464 * operations. Asynchronous operations will never fail with the error
465 * boost::asio::error::would_block.
467 BOOST_ASIO_SYNC_OP_VOID non_blocking(
468 bool mode, boost::system::error_code& ec)
470 impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);
471 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
474 /// Gets the non-blocking mode of the native descriptor implementation.
476 * This function is used to retrieve the non-blocking mode of the underlying
477 * native descriptor. This mode has no effect on the behaviour of the
478 * descriptor object's synchronous operations.
480 * @returns @c true if the underlying descriptor is in non-blocking mode and
481 * direct system calls may fail with boost::asio::error::would_block (or the
482 * equivalent system error).
484 * @note The current non-blocking mode is cached by the descriptor object.
485 * Consequently, the return value may be incorrect if the non-blocking mode
486 * was set directly on the native descriptor.
488 bool native_non_blocking() const
490 return impl_.get_service().native_non_blocking(
491 impl_.get_implementation());
494 /// Sets the non-blocking mode of the native descriptor implementation.
496 * This function is used to modify the non-blocking mode of the underlying
497 * native descriptor. It has no effect on the behaviour of the descriptor
498 * object's synchronous operations.
500 * @param mode If @c true, the underlying descriptor is put into non-blocking
501 * mode and direct system calls may fail with boost::asio::error::would_block
502 * (or the equivalent system error).
504 * @throws boost::system::system_error Thrown on failure. If the @c mode is
505 * @c false, but the current value of @c non_blocking() is @c true, this
506 * function fails with boost::asio::error::invalid_argument, as the
507 * combination does not make sense.
509 void native_non_blocking(bool mode)
511 boost::system::error_code ec;
512 impl_.get_service().native_non_blocking(
513 impl_.get_implementation(), mode, ec);
514 boost::asio::detail::throw_error(ec, "native_non_blocking");
517 /// Sets the non-blocking mode of the native descriptor implementation.
519 * This function is used to modify the non-blocking mode of the underlying
520 * native descriptor. It has no effect on the behaviour of the descriptor
521 * object's synchronous operations.
523 * @param mode If @c true, the underlying descriptor is put into non-blocking
524 * mode and direct system calls may fail with boost::asio::error::would_block
525 * (or the equivalent system error).
527 * @param ec Set to indicate what error occurred, if any. If the @c mode is
528 * @c false, but the current value of @c non_blocking() is @c true, this
529 * function fails with boost::asio::error::invalid_argument, as the
530 * combination does not make sense.
532 BOOST_ASIO_SYNC_OP_VOID native_non_blocking(
533 bool mode, boost::system::error_code& ec)
535 impl_.get_service().native_non_blocking(
536 impl_.get_implementation(), mode, ec);
537 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
540 /// Wait for the descriptor to become ready to read, ready to write, or to
541 /// have pending error conditions.
543 * This function is used to perform a blocking wait for a descriptor to enter
544 * a ready to read, write or error condition state.
546 * @param w Specifies the desired descriptor state.
549 * Waiting for a descriptor to become readable.
551 * boost::asio::posix::stream_descriptor descriptor(my_context);
553 * descriptor.wait(boost::asio::posix::stream_descriptor::wait_read);
556 void wait(wait_type w)
558 boost::system::error_code ec;
559 impl_.get_service().wait(impl_.get_implementation(), w, ec);
560 boost::asio::detail::throw_error(ec, "wait");
563 /// Wait for the descriptor to become ready to read, ready to write, or to
564 /// have pending error conditions.
566 * This function is used to perform a blocking wait for a descriptor to enter
567 * a ready to read, write or error condition state.
569 * @param w Specifies the desired descriptor state.
571 * @param ec Set to indicate what error occurred, if any.
574 * Waiting for a descriptor to become readable.
576 * boost::asio::posix::stream_descriptor descriptor(my_context);
578 * boost::system::error_code ec;
579 * descriptor.wait(boost::asio::posix::stream_descriptor::wait_read, ec);
582 BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec)
584 impl_.get_service().wait(impl_.get_implementation(), w, ec);
585 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
588 /// Asynchronously wait for the descriptor to become ready to read, ready to
589 /// write, or to have pending error conditions.
591 * This function is used to perform an asynchronous wait for a descriptor to
592 * enter a ready to read, write or error condition state.
594 * @param w Specifies the desired descriptor state.
596 * @param handler The handler to be called when the wait operation completes.
597 * Copies will be made of the handler as required. The function signature of
598 * the handler must be:
599 * @code void handler(
600 * const boost::system::error_code& error // Result of operation
602 * Regardless of whether the asynchronous operation completes immediately or
603 * not, the handler will not be invoked from within this function. On
604 * immediate completion, invocation of the handler will be performed in a
605 * manner equivalent to using boost::asio::post().
609 * void wait_handler(const boost::system::error_code& error)
619 * boost::asio::posix::stream_descriptor descriptor(my_context);
621 * descriptor.async_wait(
622 * boost::asio::posix::stream_descriptor::wait_read,
627 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))
628 WaitHandler BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
629 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,
630 void (boost::system::error_code))
631 async_wait(wait_type w,
632 BOOST_ASIO_MOVE_ARG(WaitHandler) handler
633 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
635 return async_initiate<WaitHandler, void (boost::system::error_code)>(
636 initiate_async_wait(this), handler, w);
640 /// Protected destructor to prevent deletion through this type.
642 * This function destroys the descriptor, cancelling any outstanding
643 * asynchronous wait operations associated with the descriptor as if by
650 detail::io_object_impl<detail::reactive_descriptor_service, Executor> impl_;
653 // Disallow copying and assignment.
654 basic_descriptor(const basic_descriptor&) BOOST_ASIO_DELETED;
655 basic_descriptor& operator=(const basic_descriptor&) BOOST_ASIO_DELETED;
657 class initiate_async_wait
660 typedef Executor executor_type;
662 explicit initiate_async_wait(basic_descriptor* self)
667 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
669 return self_->get_executor();
672 template <typename WaitHandler>
673 void operator()(BOOST_ASIO_MOVE_ARG(WaitHandler) handler, wait_type w) const
675 // If you get an error on the following line it means that your handler
676 // does not meet the documented type requirements for a WaitHandler.
677 BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
679 detail::non_const_lvalue<WaitHandler> handler2(handler);
680 self_->impl_.get_service().async_wait(
681 self_->impl_.get_implementation(), w, handler2.value,
682 self_->impl_.get_implementation_executor());
686 basic_descriptor* self_;
694 #include <boost/asio/detail/pop_options.hpp>
696 #endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
697 // || defined(GENERATING_DOCUMENTATION)
699 #endif // BOOST_ASIO_POSIX_BASIC_DESCRIPTOR_HPP