Chris@16: // Chris@16: // detail/reactive_descriptor_service.hpp Chris@16: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Chris@16: // Chris@101: // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: Chris@16: #ifndef BOOST_ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP Chris@16: #define BOOST_ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP Chris@16: Chris@16: #if defined(_MSC_VER) && (_MSC_VER >= 1200) Chris@16: # pragma once Chris@16: #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) Chris@16: Chris@16: #include Chris@16: Chris@16: #if !defined(BOOST_ASIO_WINDOWS) \ Chris@16: && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ Chris@16: && !defined(__CYGWIN__) Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: namespace boost { Chris@16: namespace asio { Chris@16: namespace detail { Chris@16: Chris@16: class reactive_descriptor_service Chris@16: { Chris@16: public: Chris@16: // The native type of a descriptor. Chris@16: typedef int native_handle_type; Chris@16: Chris@16: // The implementation type of the descriptor. Chris@16: class implementation_type Chris@16: : private boost::asio::detail::noncopyable Chris@16: { Chris@16: public: Chris@16: // Default constructor. Chris@16: implementation_type() Chris@16: : descriptor_(-1), Chris@16: state_(0) Chris@16: { Chris@16: } Chris@16: Chris@16: private: Chris@16: // Only this service will have access to the internal values. Chris@16: friend class reactive_descriptor_service; Chris@16: Chris@16: // The native descriptor representation. Chris@16: int descriptor_; Chris@16: Chris@16: // The current state of the descriptor. Chris@16: descriptor_ops::state_type state_; Chris@16: Chris@16: // Per-descriptor data used by the reactor. Chris@16: reactor::per_descriptor_data reactor_data_; Chris@16: }; Chris@16: Chris@16: // Constructor. Chris@16: BOOST_ASIO_DECL reactive_descriptor_service( Chris@16: boost::asio::io_service& io_service); Chris@16: Chris@16: // Destroy all user-defined handler objects owned by the service. Chris@16: BOOST_ASIO_DECL void shutdown_service(); Chris@16: Chris@16: // Construct a new descriptor implementation. Chris@16: BOOST_ASIO_DECL void construct(implementation_type& impl); Chris@16: Chris@16: // Move-construct a new descriptor implementation. Chris@16: BOOST_ASIO_DECL void move_construct(implementation_type& impl, Chris@16: implementation_type& other_impl); Chris@16: Chris@16: // Move-assign from another descriptor implementation. Chris@16: BOOST_ASIO_DECL void move_assign(implementation_type& impl, Chris@16: reactive_descriptor_service& other_service, Chris@16: implementation_type& other_impl); Chris@16: Chris@16: // Destroy a descriptor implementation. Chris@16: BOOST_ASIO_DECL void destroy(implementation_type& impl); Chris@16: Chris@16: // Assign a native descriptor to a descriptor implementation. Chris@16: BOOST_ASIO_DECL boost::system::error_code assign(implementation_type& impl, Chris@16: const native_handle_type& native_descriptor, Chris@16: boost::system::error_code& ec); Chris@16: Chris@16: // Determine whether the descriptor is open. Chris@16: bool is_open(const implementation_type& impl) const Chris@16: { Chris@16: return impl.descriptor_ != -1; Chris@16: } Chris@16: Chris@16: // Destroy a descriptor implementation. Chris@16: BOOST_ASIO_DECL boost::system::error_code close(implementation_type& impl, Chris@16: boost::system::error_code& ec); Chris@16: Chris@16: // Get the native descriptor representation. Chris@16: native_handle_type native_handle(const implementation_type& impl) const Chris@16: { Chris@16: return impl.descriptor_; Chris@16: } Chris@16: Chris@16: // Release ownership of the native descriptor representation. Chris@16: BOOST_ASIO_DECL native_handle_type release(implementation_type& impl); Chris@16: Chris@16: // Cancel all operations associated with the descriptor. Chris@16: BOOST_ASIO_DECL boost::system::error_code cancel(implementation_type& impl, Chris@16: boost::system::error_code& ec); Chris@16: Chris@16: // Perform an IO control command on the descriptor. Chris@16: template Chris@16: boost::system::error_code io_control(implementation_type& impl, Chris@16: IO_Control_Command& command, boost::system::error_code& ec) Chris@16: { Chris@16: descriptor_ops::ioctl(impl.descriptor_, impl.state_, Chris@16: command.name(), static_cast(command.data()), ec); Chris@16: return ec; Chris@16: } Chris@16: Chris@16: // Gets the non-blocking mode of the descriptor. Chris@16: bool non_blocking(const implementation_type& impl) const Chris@16: { Chris@16: return (impl.state_ & descriptor_ops::user_set_non_blocking) != 0; Chris@16: } Chris@16: Chris@16: // Sets the non-blocking mode of the descriptor. Chris@16: boost::system::error_code non_blocking(implementation_type& impl, Chris@16: bool mode, boost::system::error_code& ec) Chris@16: { Chris@16: descriptor_ops::set_user_non_blocking( Chris@16: impl.descriptor_, impl.state_, mode, ec); Chris@16: return ec; Chris@16: } Chris@16: Chris@16: // Gets the non-blocking mode of the native descriptor implementation. Chris@16: bool native_non_blocking(const implementation_type& impl) const Chris@16: { Chris@16: return (impl.state_ & descriptor_ops::internal_non_blocking) != 0; Chris@16: } Chris@16: Chris@16: // Sets the non-blocking mode of the native descriptor implementation. Chris@16: boost::system::error_code native_non_blocking(implementation_type& impl, Chris@16: bool mode, boost::system::error_code& ec) Chris@16: { Chris@16: descriptor_ops::set_internal_non_blocking( Chris@16: impl.descriptor_, impl.state_, mode, ec); Chris@16: return ec; Chris@16: } Chris@16: Chris@16: // Write some data to the descriptor. Chris@16: template Chris@16: size_t write_some(implementation_type& impl, Chris@16: const ConstBufferSequence& buffers, boost::system::error_code& ec) Chris@16: { Chris@16: buffer_sequence_adapter bufs(buffers); Chris@16: Chris@16: return descriptor_ops::sync_write(impl.descriptor_, impl.state_, Chris@16: bufs.buffers(), bufs.count(), bufs.all_empty(), ec); Chris@16: } Chris@16: Chris@16: // Wait until data can be written without blocking. Chris@16: size_t write_some(implementation_type& impl, Chris@16: const null_buffers&, boost::system::error_code& ec) Chris@16: { Chris@16: // Wait for descriptor to become ready. Chris@16: descriptor_ops::poll_write(impl.descriptor_, impl.state_, ec); Chris@16: Chris@16: return 0; Chris@16: } Chris@16: Chris@16: // Start an asynchronous write. The data being sent must be valid for the Chris@16: // lifetime of the asynchronous operation. Chris@16: template Chris@16: void async_write_some(implementation_type& impl, Chris@16: const ConstBufferSequence& buffers, Handler& handler) Chris@16: { Chris@16: bool is_continuation = Chris@16: boost_asio_handler_cont_helpers::is_continuation(handler); Chris@16: Chris@16: // Allocate and construct an operation to wrap the handler. Chris@16: typedef descriptor_write_op op; Chris@16: typename op::ptr p = { boost::asio::detail::addressof(handler), Chris@16: boost_asio_handler_alloc_helpers::allocate( Chris@16: sizeof(op), handler), 0 }; Chris@16: p.p = new (p.v) op(impl.descriptor_, buffers, handler); Chris@16: Chris@16: BOOST_ASIO_HANDLER_CREATION((p.p, "descriptor", &impl, "async_write_some")); Chris@16: Chris@16: start_op(impl, reactor::write_op, p.p, is_continuation, true, Chris@16: buffer_sequence_adapter::all_empty(buffers)); Chris@16: p.v = p.p = 0; Chris@16: } Chris@16: Chris@16: // Start an asynchronous wait until data can be written without blocking. Chris@16: template Chris@16: void async_write_some(implementation_type& impl, Chris@16: const null_buffers&, Handler& handler) Chris@16: { Chris@16: bool is_continuation = Chris@16: boost_asio_handler_cont_helpers::is_continuation(handler); Chris@16: Chris@16: // Allocate and construct an operation to wrap the handler. Chris@16: typedef reactive_null_buffers_op op; Chris@16: typename op::ptr p = { boost::asio::detail::addressof(handler), Chris@16: boost_asio_handler_alloc_helpers::allocate( Chris@16: sizeof(op), handler), 0 }; Chris@16: p.p = new (p.v) op(handler); Chris@16: Chris@16: BOOST_ASIO_HANDLER_CREATION((p.p, "descriptor", Chris@16: &impl, "async_write_some(null_buffers)")); Chris@16: Chris@16: start_op(impl, reactor::write_op, p.p, is_continuation, false, false); Chris@16: p.v = p.p = 0; Chris@16: } Chris@16: Chris@16: // Read some data from the stream. Returns the number of bytes read. Chris@16: template Chris@16: size_t read_some(implementation_type& impl, Chris@16: const MutableBufferSequence& buffers, boost::system::error_code& ec) Chris@16: { Chris@16: buffer_sequence_adapter bufs(buffers); Chris@16: Chris@16: return descriptor_ops::sync_read(impl.descriptor_, impl.state_, Chris@16: bufs.buffers(), bufs.count(), bufs.all_empty(), ec); Chris@16: } Chris@16: Chris@16: // Wait until data can be read without blocking. Chris@16: size_t read_some(implementation_type& impl, Chris@16: const null_buffers&, boost::system::error_code& ec) Chris@16: { Chris@16: // Wait for descriptor to become ready. Chris@16: descriptor_ops::poll_read(impl.descriptor_, impl.state_, ec); Chris@16: Chris@16: return 0; Chris@16: } Chris@16: Chris@16: // Start an asynchronous read. The buffer for the data being read must be Chris@16: // valid for the lifetime of the asynchronous operation. Chris@16: template Chris@16: void async_read_some(implementation_type& impl, Chris@16: const MutableBufferSequence& buffers, Handler& handler) Chris@16: { Chris@16: bool is_continuation = Chris@16: boost_asio_handler_cont_helpers::is_continuation(handler); Chris@16: Chris@16: // Allocate and construct an operation to wrap the handler. Chris@16: typedef descriptor_read_op op; Chris@16: typename op::ptr p = { boost::asio::detail::addressof(handler), Chris@16: boost_asio_handler_alloc_helpers::allocate( Chris@16: sizeof(op), handler), 0 }; Chris@16: p.p = new (p.v) op(impl.descriptor_, buffers, handler); Chris@16: Chris@16: BOOST_ASIO_HANDLER_CREATION((p.p, "descriptor", &impl, "async_read_some")); Chris@16: Chris@16: start_op(impl, reactor::read_op, p.p, is_continuation, true, Chris@16: buffer_sequence_adapter::all_empty(buffers)); Chris@16: p.v = p.p = 0; Chris@16: } Chris@16: Chris@16: // Wait until data can be read without blocking. Chris@16: template Chris@16: void async_read_some(implementation_type& impl, Chris@16: const null_buffers&, Handler& handler) Chris@16: { Chris@16: bool is_continuation = Chris@16: boost_asio_handler_cont_helpers::is_continuation(handler); Chris@16: Chris@16: // Allocate and construct an operation to wrap the handler. Chris@16: typedef reactive_null_buffers_op op; Chris@16: typename op::ptr p = { boost::asio::detail::addressof(handler), Chris@16: boost_asio_handler_alloc_helpers::allocate( Chris@16: sizeof(op), handler), 0 }; Chris@16: p.p = new (p.v) op(handler); Chris@16: Chris@16: BOOST_ASIO_HANDLER_CREATION((p.p, "descriptor", Chris@16: &impl, "async_read_some(null_buffers)")); Chris@16: Chris@16: start_op(impl, reactor::read_op, p.p, is_continuation, false, false); Chris@16: p.v = p.p = 0; Chris@16: } Chris@16: Chris@16: private: Chris@16: // Start the asynchronous operation. Chris@16: BOOST_ASIO_DECL void start_op(implementation_type& impl, int op_type, Chris@16: reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop); Chris@16: Chris@16: // The selector that performs event demultiplexing for the service. Chris@16: reactor& reactor_; Chris@16: }; Chris@16: Chris@16: } // namespace detail Chris@16: } // namespace asio Chris@16: } // namespace boost Chris@16: Chris@16: #include Chris@16: Chris@16: #if defined(BOOST_ASIO_HEADER_ONLY) Chris@16: # include Chris@16: #endif // defined(BOOST_ASIO_HEADER_ONLY) Chris@16: Chris@16: #endif // !defined(BOOST_ASIO_WINDOWS) Chris@16: // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) Chris@16: // && !defined(__CYGWIN__) Chris@16: Chris@16: #endif // BOOST_ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP