You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
323 lines
12 KiB
323 lines
12 KiB
// |
|
// detail/win_iocp_handle_service.hpp |
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
// |
|
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
|
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.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_WIN_IOCP_HANDLE_SERVICE_HPP |
|
#define BOOST_ASIO_DETAIL_WIN_IOCP_HANDLE_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_ASIO_HAS_IOCP) |
|
|
|
#include <boost/cstdint.hpp> |
|
#include <boost/asio/error.hpp> |
|
#include <boost/asio/io_service.hpp> |
|
#include <boost/asio/detail/buffer_sequence_adapter.hpp> |
|
#include <boost/asio/detail/handler_alloc_helpers.hpp> |
|
#include <boost/asio/detail/mutex.hpp> |
|
#include <boost/asio/detail/operation.hpp> |
|
#include <boost/asio/detail/win_iocp_handle_read_op.hpp> |
|
#include <boost/asio/detail/win_iocp_handle_write_op.hpp> |
|
#include <boost/asio/detail/win_iocp_io_service.hpp> |
|
|
|
#include <boost/asio/detail/push_options.hpp> |
|
|
|
namespace boost { |
|
namespace asio { |
|
namespace detail { |
|
|
|
class win_iocp_handle_service |
|
{ |
|
public: |
|
// The native type of a stream handle. |
|
typedef HANDLE native_handle_type; |
|
|
|
// The implementation type of the stream handle. |
|
class implementation_type |
|
{ |
|
public: |
|
// Default constructor. |
|
implementation_type() |
|
: handle_(INVALID_HANDLE_VALUE), |
|
safe_cancellation_thread_id_(0), |
|
next_(0), |
|
prev_(0) |
|
{ |
|
} |
|
|
|
private: |
|
// Only this service will have access to the internal values. |
|
friend class win_iocp_handle_service; |
|
|
|
// The native stream handle representation. |
|
native_handle_type handle_; |
|
|
|
// The ID of the thread from which it is safe to cancel asynchronous |
|
// operations. 0 means no asynchronous operations have been started yet. |
|
// ~0 means asynchronous operations have been started from more than one |
|
// thread, and cancellation is not supported for the handle. |
|
DWORD safe_cancellation_thread_id_; |
|
|
|
// Pointers to adjacent handle implementations in linked list. |
|
implementation_type* next_; |
|
implementation_type* prev_; |
|
}; |
|
|
|
BOOST_ASIO_DECL win_iocp_handle_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 handle implementation. |
|
BOOST_ASIO_DECL void construct(implementation_type& impl); |
|
|
|
// Move-construct a new handle implementation. |
|
BOOST_ASIO_DECL void move_construct(implementation_type& impl, |
|
implementation_type& other_impl); |
|
|
|
// Move-assign from another handle implementation. |
|
BOOST_ASIO_DECL void move_assign(implementation_type& impl, |
|
win_iocp_handle_service& other_service, |
|
implementation_type& other_impl); |
|
|
|
// Destroy a handle implementation. |
|
BOOST_ASIO_DECL void destroy(implementation_type& impl); |
|
|
|
// Assign a native handle to a handle implementation. |
|
BOOST_ASIO_DECL boost::system::error_code assign(implementation_type& impl, |
|
const native_handle_type& handle, boost::system::error_code& ec); |
|
|
|
// Determine whether the handle is open. |
|
bool is_open(const implementation_type& impl) const |
|
{ |
|
return impl.handle_ != INVALID_HANDLE_VALUE; |
|
} |
|
|
|
// Destroy a handle implementation. |
|
BOOST_ASIO_DECL boost::system::error_code close(implementation_type& impl, |
|
boost::system::error_code& ec); |
|
|
|
// Get the native handle representation. |
|
native_handle_type native_handle(const implementation_type& impl) const |
|
{ |
|
return impl.handle_; |
|
} |
|
|
|
// Cancel all operations associated with the handle. |
|
BOOST_ASIO_DECL boost::system::error_code cancel(implementation_type& impl, |
|
boost::system::error_code& ec); |
|
|
|
// Write the given data. Returns the number of bytes written. |
|
template <typename ConstBufferSequence> |
|
size_t write_some(implementation_type& impl, |
|
const ConstBufferSequence& buffers, boost::system::error_code& ec) |
|
{ |
|
return write_some_at(impl, 0, buffers, ec); |
|
} |
|
|
|
// Write the given data at the specified offset. Returns the number of bytes |
|
// written. |
|
template <typename ConstBufferSequence> |
|
size_t write_some_at(implementation_type& impl, boost::uint64_t offset, |
|
const ConstBufferSequence& buffers, boost::system::error_code& ec) |
|
{ |
|
boost::asio::const_buffer buffer = |
|
buffer_sequence_adapter<boost::asio::const_buffer, |
|
ConstBufferSequence>::first(buffers); |
|
|
|
return do_write(impl, offset, buffer, ec); |
|
} |
|
|
|
// Start an asynchronous write. The data being written 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 win_iocp_handle_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(buffers, handler); |
|
|
|
BOOST_ASIO_HANDLER_CREATION((p.p, "handle", &impl, "async_write_some")); |
|
|
|
start_write_op(impl, 0, |
|
buffer_sequence_adapter<boost::asio::const_buffer, |
|
ConstBufferSequence>::first(buffers), p.p); |
|
p.v = p.p = 0; |
|
} |
|
|
|
// Start an asynchronous write at a specified offset. The data being written |
|
// must be valid for the lifetime of the asynchronous operation. |
|
template <typename ConstBufferSequence, typename Handler> |
|
void async_write_some_at(implementation_type& impl, boost::uint64_t offset, |
|
const ConstBufferSequence& buffers, Handler handler) |
|
{ |
|
// Allocate and construct an operation to wrap the handler. |
|
typedef win_iocp_handle_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(buffers, handler); |
|
|
|
BOOST_ASIO_HANDLER_CREATION((p.p, "handle", &impl, "async_write_some_at")); |
|
|
|
start_write_op(impl, offset, |
|
buffer_sequence_adapter<boost::asio::const_buffer, |
|
ConstBufferSequence>::first(buffers), p.p); |
|
p.v = p.p = 0; |
|
} |
|
|
|
// Read some data. Returns the number of bytes received. |
|
template <typename MutableBufferSequence> |
|
size_t read_some(implementation_type& impl, |
|
const MutableBufferSequence& buffers, boost::system::error_code& ec) |
|
{ |
|
return read_some_at(impl, 0, buffers, ec); |
|
} |
|
|
|
// Read some data at a specified offset. Returns the number of bytes received. |
|
template <typename MutableBufferSequence> |
|
size_t read_some_at(implementation_type& impl, boost::uint64_t offset, |
|
const MutableBufferSequence& buffers, boost::system::error_code& ec) |
|
{ |
|
boost::asio::mutable_buffer buffer = |
|
buffer_sequence_adapter<boost::asio::mutable_buffer, |
|
MutableBufferSequence>::first(buffers); |
|
|
|
return do_read(impl, offset, buffer, ec); |
|
} |
|
|
|
// Start an asynchronous read. The buffer for the data being received 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 win_iocp_handle_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(buffers, handler); |
|
|
|
BOOST_ASIO_HANDLER_CREATION((p.p, "handle", &impl, "async_read_some")); |
|
|
|
start_read_op(impl, 0, |
|
buffer_sequence_adapter<boost::asio::mutable_buffer, |
|
MutableBufferSequence>::first(buffers), p.p); |
|
p.v = p.p = 0; |
|
} |
|
|
|
// Start an asynchronous read at a specified offset. The buffer for the data |
|
// being received must be valid for the lifetime of the asynchronous |
|
// operation. |
|
template <typename MutableBufferSequence, typename Handler> |
|
void async_read_some_at(implementation_type& impl, boost::uint64_t offset, |
|
const MutableBufferSequence& buffers, Handler handler) |
|
{ |
|
// Allocate and construct an operation to wrap the handler. |
|
typedef win_iocp_handle_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(buffers, handler); |
|
|
|
BOOST_ASIO_HANDLER_CREATION((p.p, "handle", &impl, "async_read_some_at")); |
|
|
|
start_read_op(impl, offset, |
|
buffer_sequence_adapter<boost::asio::mutable_buffer, |
|
MutableBufferSequence>::first(buffers), p.p); |
|
p.v = p.p = 0; |
|
} |
|
|
|
private: |
|
// Prevent the use of the null_buffers type with this service. |
|
size_t write_some(implementation_type& impl, |
|
const null_buffers& buffers, boost::system::error_code& ec); |
|
size_t write_some_at(implementation_type& impl, boost::uint64_t offset, |
|
const null_buffers& buffers, boost::system::error_code& ec); |
|
template <typename Handler> |
|
void async_write_some(implementation_type& impl, |
|
const null_buffers& buffers, Handler handler); |
|
template <typename Handler> |
|
void async_write_some_at(implementation_type& impl, boost::uint64_t offset, |
|
const null_buffers& buffers, Handler handler); |
|
size_t read_some(implementation_type& impl, |
|
const null_buffers& buffers, boost::system::error_code& ec); |
|
size_t read_some_at(implementation_type& impl, boost::uint64_t offset, |
|
const null_buffers& buffers, boost::system::error_code& ec); |
|
template <typename Handler> |
|
void async_read_some(implementation_type& impl, |
|
const null_buffers& buffers, Handler handler); |
|
template <typename Handler> |
|
void async_read_some_at(implementation_type& impl, boost::uint64_t offset, |
|
const null_buffers& buffers, Handler handler); |
|
|
|
// Helper class for waiting for synchronous operations to complete. |
|
class overlapped_wrapper; |
|
|
|
// Helper function to perform a synchronous write operation. |
|
BOOST_ASIO_DECL size_t do_write(implementation_type& impl, |
|
boost::uint64_t offset, const boost::asio::const_buffer& buffer, |
|
boost::system::error_code& ec); |
|
|
|
// Helper function to start a write operation. |
|
BOOST_ASIO_DECL void start_write_op(implementation_type& impl, |
|
boost::uint64_t offset, const boost::asio::const_buffer& buffer, |
|
operation* op); |
|
|
|
// Helper function to perform a synchronous write operation. |
|
BOOST_ASIO_DECL size_t do_read(implementation_type& impl, |
|
boost::uint64_t offset, const boost::asio::mutable_buffer& buffer, |
|
boost::system::error_code& ec); |
|
|
|
// Helper function to start a read operation. |
|
BOOST_ASIO_DECL void start_read_op(implementation_type& impl, |
|
boost::uint64_t offset, const boost::asio::mutable_buffer& buffer, |
|
operation* op); |
|
|
|
// Update the ID of the thread from which cancellation is safe. |
|
BOOST_ASIO_DECL void update_cancellation_thread_id(implementation_type& impl); |
|
|
|
// Helper function to close a handle when the associated object is being |
|
// destroyed. |
|
BOOST_ASIO_DECL void close_for_destruction(implementation_type& impl); |
|
|
|
// The IOCP service used for running asynchronous operations and dispatching |
|
// handlers. |
|
win_iocp_io_service& iocp_service_; |
|
|
|
// Mutex to protect access to the linked list of implementations. |
|
mutex mutex_; |
|
|
|
// The head of a linked list of all implementations. |
|
implementation_type* impl_list_; |
|
}; |
|
|
|
} // namespace detail |
|
} // namespace asio |
|
} // namespace boost |
|
|
|
#include <boost/asio/detail/pop_options.hpp> |
|
|
|
#if defined(BOOST_ASIO_HEADER_ONLY) |
|
# include <boost/asio/detail/impl/win_iocp_handle_service.ipp> |
|
#endif // defined(BOOST_ASIO_HEADER_ONLY) |
|
|
|
#endif // defined(BOOST_ASIO_HAS_IOCP) |
|
|
|
#endif // BOOST_ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP
|
|
|