2 // posix/basic_descriptor.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2017 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_ENABLE_OLD_SERVICES)
22 #if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
23 || defined(GENERATING_DOCUMENTATION)
25 #include <boost/asio/basic_io_object.hpp>
26 #include <boost/asio/detail/throw_error.hpp>
27 #include <boost/asio/error.hpp>
28 #include <boost/asio/posix/descriptor_base.hpp>
30 #include <boost/asio/detail/push_options.hpp>
36 /// Provides POSIX descriptor functionality.
38 * The posix::basic_descriptor class template provides the ability to wrap a
42 * @e Distinct @e objects: Safe.@n
43 * @e Shared @e objects: Unsafe.
45 template <typename DescriptorService>
46 class basic_descriptor
47 : public basic_io_object<DescriptorService>,
48 public descriptor_base
51 /// The native representation of a descriptor.
52 typedef typename DescriptorService::native_handle_type native_handle_type;
54 /// A basic_descriptor is always the lowest layer.
55 typedef basic_descriptor<DescriptorService> lowest_layer_type;
57 /// Construct a basic_descriptor without opening it.
59 * This constructor creates a descriptor without opening it.
61 * @param io_context The io_context object that the descriptor will use to
62 * dispatch handlers for any asynchronous operations performed on the
65 explicit basic_descriptor(boost::asio::io_context& io_context)
66 : basic_io_object<DescriptorService>(io_context)
70 /// Construct a basic_descriptor on an existing native descriptor.
72 * This constructor creates a descriptor object to hold an existing native
75 * @param io_context The io_context object that the descriptor will use to
76 * dispatch handlers for any asynchronous operations performed on the
79 * @param native_descriptor A native descriptor.
81 * @throws boost::system::system_error Thrown on failure.
83 basic_descriptor(boost::asio::io_context& io_context,
84 const native_handle_type& native_descriptor)
85 : basic_io_object<DescriptorService>(io_context)
87 boost::system::error_code ec;
88 this->get_service().assign(this->get_implementation(),
89 native_descriptor, ec);
90 boost::asio::detail::throw_error(ec, "assign");
93 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
94 /// Move-construct a basic_descriptor from another.
96 * This constructor moves a descriptor from one object to another.
98 * @param other The other basic_descriptor object from which the move will
101 * @note Following the move, the moved-from object is in the same state as if
102 * constructed using the @c basic_descriptor(io_context&) constructor.
104 basic_descriptor(basic_descriptor&& other)
105 : basic_io_object<DescriptorService>(
106 BOOST_ASIO_MOVE_CAST(basic_descriptor)(other))
110 /// Move-assign a basic_descriptor from another.
112 * This assignment operator moves a descriptor from one object to another.
114 * @param other The other basic_descriptor object from which the move will
117 * @note Following the move, the moved-from object is in the same state as if
118 * constructed using the @c basic_descriptor(io_context&) constructor.
120 basic_descriptor& operator=(basic_descriptor&& other)
122 basic_io_object<DescriptorService>::operator=(
123 BOOST_ASIO_MOVE_CAST(basic_descriptor)(other));
126 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
128 /// Get a reference to the lowest layer.
130 * This function returns a reference to the lowest layer in a stack of
131 * layers. Since a basic_descriptor cannot contain any further layers, it
132 * simply returns a reference to itself.
134 * @return A reference to the lowest layer in the stack of layers. Ownership
135 * is not transferred to the caller.
137 lowest_layer_type& lowest_layer()
142 /// Get a const reference to the lowest layer.
144 * This function returns a const reference to the lowest layer in a stack of
145 * layers. Since a basic_descriptor cannot contain any further layers, it
146 * simply returns a reference to itself.
148 * @return A const reference to the lowest layer in the stack of layers.
149 * Ownership is not transferred to the caller.
151 const lowest_layer_type& lowest_layer() const
156 /// Assign an existing native descriptor to the descriptor.
158 * This function opens the descriptor to hold an existing native descriptor.
160 * @param native_descriptor A native descriptor.
162 * @throws boost::system::system_error Thrown on failure.
164 void assign(const native_handle_type& native_descriptor)
166 boost::system::error_code ec;
167 this->get_service().assign(this->get_implementation(),
168 native_descriptor, ec);
169 boost::asio::detail::throw_error(ec, "assign");
172 /// Assign an existing native descriptor to the descriptor.
174 * This function opens the descriptor to hold an existing native descriptor.
176 * @param native_descriptor A native descriptor.
178 * @param ec Set to indicate what error occurred, if any.
180 BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& native_descriptor,
181 boost::system::error_code& ec)
183 this->get_service().assign(
184 this->get_implementation(), native_descriptor, ec);
185 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
188 /// Determine whether the descriptor is open.
191 return this->get_service().is_open(this->get_implementation());
194 /// Close the descriptor.
196 * This function is used to close the descriptor. Any asynchronous read or
197 * write operations will be cancelled immediately, and will complete with the
198 * boost::asio::error::operation_aborted error.
200 * @throws boost::system::system_error Thrown on failure. Note that, even if
201 * the function indicates an error, the underlying descriptor is closed.
205 boost::system::error_code ec;
206 this->get_service().close(this->get_implementation(), ec);
207 boost::asio::detail::throw_error(ec, "close");
210 /// Close the descriptor.
212 * This function is used to close the descriptor. Any asynchronous read or
213 * write operations will be cancelled immediately, and will complete with the
214 * boost::asio::error::operation_aborted error.
216 * @param ec Set to indicate what error occurred, if any. Note that, even if
217 * the function indicates an error, the underlying descriptor is closed.
219 BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
221 this->get_service().close(this->get_implementation(), ec);
222 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
225 /// Get the native descriptor representation.
227 * This function may be used to obtain the underlying representation of the
228 * descriptor. This is intended to allow access to native descriptor
229 * functionality that is not otherwise provided.
231 native_handle_type native_handle()
233 return this->get_service().native_handle(this->get_implementation());
236 /// Release ownership of the native descriptor implementation.
238 * This function may be used to obtain the underlying representation of the
239 * descriptor. After calling this function, @c is_open() returns false. The
240 * caller is responsible for closing the descriptor.
242 * All outstanding asynchronous read or write operations will finish
243 * immediately, and the handlers for cancelled operations will be passed the
244 * boost::asio::error::operation_aborted error.
246 native_handle_type release()
248 return this->get_service().release(this->get_implementation());
251 /// Cancel all asynchronous operations associated with the descriptor.
253 * This function causes all outstanding asynchronous read or write operations
254 * to finish immediately, and the handlers for cancelled operations will be
255 * passed the boost::asio::error::operation_aborted error.
257 * @throws boost::system::system_error Thrown on failure.
261 boost::system::error_code ec;
262 this->get_service().cancel(this->get_implementation(), ec);
263 boost::asio::detail::throw_error(ec, "cancel");
266 /// Cancel all asynchronous operations associated with the descriptor.
268 * This function causes all outstanding asynchronous read or write operations
269 * to finish immediately, and the handlers for cancelled operations will be
270 * passed the boost::asio::error::operation_aborted error.
272 * @param ec Set to indicate what error occurred, if any.
274 BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
276 this->get_service().cancel(this->get_implementation(), ec);
277 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
280 /// Perform an IO control command on the descriptor.
282 * This function is used to execute an IO control command on the descriptor.
284 * @param command The IO control command to be performed on the descriptor.
286 * @throws boost::system::system_error Thrown on failure.
288 * @sa IoControlCommand @n
289 * boost::asio::posix::descriptor_base::bytes_readable @n
290 * boost::asio::posix::descriptor_base::non_blocking_io
293 * Getting the number of bytes ready to read:
295 * boost::asio::posix::stream_descriptor descriptor(io_context);
297 * boost::asio::posix::stream_descriptor::bytes_readable command;
298 * descriptor.io_control(command);
299 * std::size_t bytes_readable = command.get();
302 template <typename IoControlCommand>
303 void io_control(IoControlCommand& command)
305 boost::system::error_code ec;
306 this->get_service().io_control(this->get_implementation(), command, ec);
307 boost::asio::detail::throw_error(ec, "io_control");
310 /// Perform an IO control command on the descriptor.
312 * This function is used to execute an IO control command on the descriptor.
314 * @param command The IO control command to be performed on the descriptor.
316 * @param ec Set to indicate what error occurred, if any.
318 * @sa IoControlCommand @n
319 * boost::asio::posix::descriptor_base::bytes_readable @n
320 * boost::asio::posix::descriptor_base::non_blocking_io
323 * Getting the number of bytes ready to read:
325 * boost::asio::posix::stream_descriptor descriptor(io_context);
327 * boost::asio::posix::stream_descriptor::bytes_readable command;
328 * boost::system::error_code ec;
329 * descriptor.io_control(command, ec);
332 * // An error occurred.
334 * std::size_t bytes_readable = command.get();
337 template <typename IoControlCommand>
338 BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command,
339 boost::system::error_code& ec)
341 this->get_service().io_control(this->get_implementation(), command, ec);
342 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
345 /// Gets the non-blocking mode of the descriptor.
347 * @returns @c true if the descriptor's synchronous operations will fail with
348 * boost::asio::error::would_block if they are unable to perform the requested
349 * operation immediately. If @c false, synchronous operations will block
352 * @note The non-blocking mode has no effect on the behaviour of asynchronous
353 * operations. Asynchronous operations will never fail with the error
354 * boost::asio::error::would_block.
356 bool non_blocking() const
358 return this->get_service().non_blocking(this->get_implementation());
361 /// Sets the non-blocking mode of the descriptor.
363 * @param mode If @c true, the descriptor's synchronous operations will fail
364 * with boost::asio::error::would_block if they are unable to perform the
365 * requested operation immediately. If @c false, synchronous operations will
366 * block until complete.
368 * @throws boost::system::system_error Thrown on failure.
370 * @note The non-blocking mode has no effect on the behaviour of asynchronous
371 * operations. Asynchronous operations will never fail with the error
372 * boost::asio::error::would_block.
374 void non_blocking(bool mode)
376 boost::system::error_code ec;
377 this->get_service().non_blocking(this->get_implementation(), mode, ec);
378 boost::asio::detail::throw_error(ec, "non_blocking");
381 /// Sets the non-blocking mode of the descriptor.
383 * @param mode If @c true, the descriptor's synchronous operations will fail
384 * with boost::asio::error::would_block if they are unable to perform the
385 * requested operation immediately. If @c false, synchronous operations will
386 * block until complete.
388 * @param ec Set to indicate what error occurred, if any.
390 * @note The non-blocking mode has no effect on the behaviour of asynchronous
391 * operations. Asynchronous operations will never fail with the error
392 * boost::asio::error::would_block.
394 BOOST_ASIO_SYNC_OP_VOID non_blocking(
395 bool mode, boost::system::error_code& ec)
397 this->get_service().non_blocking(this->get_implementation(), mode, ec);
398 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
401 /// Gets the non-blocking mode of the native descriptor implementation.
403 * This function is used to retrieve the non-blocking mode of the underlying
404 * native descriptor. This mode has no effect on the behaviour of the
405 * descriptor object's synchronous operations.
407 * @returns @c true if the underlying descriptor is in non-blocking mode and
408 * direct system calls may fail with boost::asio::error::would_block (or the
409 * equivalent system error).
411 * @note The current non-blocking mode is cached by the descriptor object.
412 * Consequently, the return value may be incorrect if the non-blocking mode
413 * was set directly on the native descriptor.
415 bool native_non_blocking() const
417 return this->get_service().native_non_blocking(
418 this->get_implementation());
421 /// Sets the non-blocking mode of the native descriptor implementation.
423 * This function is used to modify the non-blocking mode of the underlying
424 * native descriptor. It has no effect on the behaviour of the descriptor
425 * object's synchronous operations.
427 * @param mode If @c true, the underlying descriptor is put into non-blocking
428 * mode and direct system calls may fail with boost::asio::error::would_block
429 * (or the equivalent system error).
431 * @throws boost::system::system_error Thrown on failure. If the @c mode is
432 * @c false, but the current value of @c non_blocking() is @c true, this
433 * function fails with boost::asio::error::invalid_argument, as the
434 * combination does not make sense.
436 void native_non_blocking(bool mode)
438 boost::system::error_code ec;
439 this->get_service().native_non_blocking(
440 this->get_implementation(), mode, ec);
441 boost::asio::detail::throw_error(ec, "native_non_blocking");
444 /// Sets the non-blocking mode of the native descriptor implementation.
446 * This function is used to modify the non-blocking mode of the underlying
447 * native descriptor. It has no effect on the behaviour of the descriptor
448 * object's synchronous operations.
450 * @param mode If @c true, the underlying descriptor is put into non-blocking
451 * mode and direct system calls may fail with boost::asio::error::would_block
452 * (or the equivalent system error).
454 * @param ec Set to indicate what error occurred, if any. If the @c mode is
455 * @c false, but the current value of @c non_blocking() is @c true, this
456 * function fails with boost::asio::error::invalid_argument, as the
457 * combination does not make sense.
459 BOOST_ASIO_SYNC_OP_VOID native_non_blocking(
460 bool mode, boost::system::error_code& ec)
462 this->get_service().native_non_blocking(
463 this->get_implementation(), mode, ec);
464 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
467 /// Wait for the descriptor to become ready to read, ready to write, or to
468 /// have pending error conditions.
470 * This function is used to perform a blocking wait for a descriptor to enter
471 * a ready to read, write or error condition state.
473 * @param w Specifies the desired descriptor state.
476 * Waiting for a descriptor to become readable.
478 * boost::asio::posix::stream_descriptor descriptor(io_context);
480 * descriptor.wait(boost::asio::posix::stream_descriptor::wait_read);
483 void wait(wait_type w)
485 boost::system::error_code ec;
486 this->get_service().wait(this->get_implementation(), w, ec);
487 boost::asio::detail::throw_error(ec, "wait");
490 /// Wait for the descriptor to become ready to read, ready to write, or to
491 /// have pending error conditions.
493 * This function is used to perform a blocking wait for a descriptor to enter
494 * a ready to read, write or error condition state.
496 * @param w Specifies the desired descriptor state.
498 * @param ec Set to indicate what error occurred, if any.
501 * Waiting for a descriptor to become readable.
503 * boost::asio::posix::stream_descriptor descriptor(io_context);
505 * boost::system::error_code ec;
506 * descriptor.wait(boost::asio::posix::stream_descriptor::wait_read, ec);
509 BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec)
511 this->get_service().wait(this->get_implementation(), w, ec);
512 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
515 /// Asynchronously wait for the descriptor to become ready to read, ready to
516 /// write, or to have pending error conditions.
518 * This function is used to perform an asynchronous wait for a descriptor to
519 * enter a ready to read, write or error condition state.
521 * @param w Specifies the desired descriptor state.
523 * @param handler The handler to be called when the wait operation completes.
524 * Copies will be made of the handler as required. The function signature of
525 * the handler must be:
526 * @code void handler(
527 * const boost::system::error_code& error // Result of operation
529 * Regardless of whether the asynchronous operation completes immediately or
530 * not, the handler will not be invoked from within this function. Invocation
531 * of the handler will be performed in a manner equivalent to using
532 * boost::asio::io_context::post().
536 * void wait_handler(const boost::system::error_code& error)
546 * boost::asio::posix::stream_descriptor descriptor(io_context);
548 * descriptor.async_wait(
549 * boost::asio::posix::stream_descriptor::wait_read,
553 template <typename WaitHandler>
554 BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
555 void (boost::system::error_code))
556 async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
558 // If you get an error on the following line it means that your handler does
559 // not meet the documented type requirements for a WaitHandler.
560 BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
562 return this->get_service().async_wait(this->get_implementation(),
563 w, BOOST_ASIO_MOVE_CAST(WaitHandler)(handler));
567 /// Protected destructor to prevent deletion through this type.
577 #include <boost/asio/detail/pop_options.hpp>
579 #endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
580 // || defined(GENERATING_DOCUMENTATION)
582 #endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
584 #endif // BOOST_ASIO_POSIX_BASIC_DESCRIPTOR_HPP