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