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