⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 win_iocp_handle_service.hpp

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 HPP
📖 第 1 页 / 共 2 页
字号:
    static void destroy_impl(operation* op)    {      // Take ownership of the operation object.      typedef write_operation<ConstBufferSequence, Handler> op_type;      op_type* handler_op(static_cast<op_type*>(op));      typedef handler_alloc_traits<Handler, op_type> alloc_traits;      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);      // A sub-object of the handler may be the true owner of the memory      // associated with the handler. Consequently, a local copy of the handler      // is required to ensure that any owning sub-object remains valid until      // after we have deallocated the memory here.      Handler handler(handler_op->handler_);      (void)handler;      // Free the memory associated with the handler.      ptr.reset();    }    boost::asio::io_service::work work_;    ConstBufferSequence buffers_;    Handler handler_;  };  // 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)  {    async_write_some_at(impl, 0, buffers, handler);  }  // 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)  {    if (!is_open(impl))    {      this->get_io_service().post(bind_handler(handler,            boost::asio::error::bad_descriptor, 0));      return;    }    // Update the ID of the thread from which cancellation is safe.    if (impl.safe_cancellation_thread_id_ == 0)      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())      impl.safe_cancellation_thread_id_ = ~DWORD(0);    // Allocate and construct an operation to wrap the handler.    typedef write_operation<ConstBufferSequence, Handler> value_type;    typedef handler_alloc_traits<Handler, value_type> alloc_traits;    raw_handler_ptr<alloc_traits> raw_ptr(handler);    handler_ptr<alloc_traits> ptr(raw_ptr, iocp_service_, buffers, handler);    // Find first buffer of non-zero length.    boost::asio::const_buffer buffer;    typename ConstBufferSequence::const_iterator iter = buffers.begin();    typename ConstBufferSequence::const_iterator end = buffers.end();    for (DWORD i = 0; iter != end; ++iter, ++i)    {      buffer = boost::asio::const_buffer(*iter);      if (boost::asio::buffer_size(buffer) != 0)        break;    }    // A request to write 0 bytes on a handle is a no-op.    if (boost::asio::buffer_size(buffer) == 0)    {      boost::asio::io_service::work work(this->get_io_service());      ptr.reset();      boost::system::error_code error;      iocp_service_.post(bind_handler(handler, error, 0));      return;    }    // Write the data.    DWORD bytes_transferred = 0;    ptr.get()->Offset = offset & 0xFFFFFFFF;    ptr.get()->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;    BOOL ok = ::WriteFile(impl.handle_,        boost::asio::buffer_cast<LPCVOID>(buffer),        static_cast<DWORD>(boost::asio::buffer_size(buffer)),        &bytes_transferred, ptr.get());    DWORD last_error = ::GetLastError();    // Check if the operation completed immediately.    if (!ok && last_error != ERROR_IO_PENDING)    {      boost::asio::io_service::work work(this->get_io_service());      ptr.reset();      boost::system::error_code ec(last_error,          boost::asio::error::get_system_category());      iocp_service_.post(bind_handler(handler, ec, bytes_transferred));    }    else    {      ptr.release();    }  }  // 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)  {    if (!is_open(impl))    {      ec = boost::asio::error::bad_descriptor;      return 0;    }        // Find first buffer of non-zero length.    boost::asio::mutable_buffer buffer;    typename MutableBufferSequence::const_iterator iter = buffers.begin();    typename MutableBufferSequence::const_iterator end = buffers.end();    for (DWORD i = 0; iter != end; ++iter, ++i)    {      buffer = boost::asio::mutable_buffer(*iter);      if (boost::asio::buffer_size(buffer) != 0)        break;    }    // A request to read 0 bytes on a stream handle is a no-op.    if (boost::asio::buffer_size(buffer) == 0)    {      ec = boost::system::error_code();      return 0;    }    overlapped_wrapper overlapped(ec);    if (ec)    {      return 0;    }    // Read some data.    overlapped.Offset = offset & 0xFFFFFFFF;    overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF;    BOOL ok = ::ReadFile(impl.handle_,        boost::asio::buffer_cast<LPVOID>(buffer),        static_cast<DWORD>(boost::asio::buffer_size(buffer)), 0, &overlapped);    if (!ok)     {      DWORD last_error = ::GetLastError();      if (last_error != ERROR_IO_PENDING)      {        if (last_error == ERROR_HANDLE_EOF)        {          ec = boost::asio::error::eof;        }        else        {          ec = boost::system::error_code(last_error,              boost::asio::error::get_system_category());        }        return 0;      }    }    // Wait for the operation to complete.    DWORD bytes_transferred = 0;    ok = ::GetOverlappedResult(impl.handle_,        &overlapped, &bytes_transferred, TRUE);    if (!ok)    {      DWORD last_error = ::GetLastError();      if (last_error == ERROR_HANDLE_EOF)      {        ec = boost::asio::error::eof;      }      else      {        ec = boost::system::error_code(last_error,            boost::asio::error::get_system_category());      }    }    ec = boost::system::error_code();    return bytes_transferred;  }  template <typename MutableBufferSequence, typename Handler>  class read_operation    : public operation  {  public:    read_operation(win_iocp_io_service& io_service,        const MutableBufferSequence& buffers, Handler handler)      : operation(io_service,          &read_operation<            MutableBufferSequence, Handler>::do_completion_impl,          &read_operation<            MutableBufferSequence, Handler>::destroy_impl),        work_(io_service.get_io_service()),        buffers_(buffers),        handler_(handler)    {    }  private:    static void do_completion_impl(operation* op,        DWORD last_error, size_t bytes_transferred)    {      // Take ownership of the operation object.      typedef read_operation<MutableBufferSequence, Handler> op_type;      op_type* handler_op(static_cast<op_type*>(op));      typedef handler_alloc_traits<Handler, op_type> alloc_traits;      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)      // Check whether buffers are still valid.      typename MutableBufferSequence::const_iterator iter        = handler_op->buffers_.begin();      typename MutableBufferSequence::const_iterator end        = handler_op->buffers_.end();      while (iter != end)      {        boost::asio::mutable_buffer buffer(*iter);        boost::asio::buffer_cast<char*>(buffer);        ++iter;      }#endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)      // Check for the end-of-file condition.      boost::system::error_code ec(last_error,          boost::asio::error::get_system_category());      if (!ec && bytes_transferred == 0 || last_error == ERROR_HANDLE_EOF)      {        ec = boost::asio::error::eof;      }      // Make a copy of the handler so that the memory can be deallocated before      // the upcall is made.      Handler handler(handler_op->handler_);      // Free the memory associated with the handler.      ptr.reset();      // Call the handler.      boost_asio_handler_invoke_helpers::invoke(        bind_handler(handler, ec, bytes_transferred), &handler);    }    static void destroy_impl(operation* op)    {      // Take ownership of the operation object.      typedef read_operation<MutableBufferSequence, Handler> op_type;      op_type* handler_op(static_cast<op_type*>(op));      typedef boost::asio::detail::handler_alloc_traits<        Handler, op_type> alloc_traits;      boost::asio::detail::handler_ptr<alloc_traits> ptr(        handler_op->handler_, handler_op);      // A sub-object of the handler may be the true owner of the memory      // associated with the handler. Consequently, a local copy of the handler      // is required to ensure that any owning sub-object remains valid until      // after we have deallocated the memory here.      Handler handler(handler_op->handler_);      (void)handler;      // Free the memory associated with the handler.      ptr.reset();    }    boost::asio::io_service::work work_;    MutableBufferSequence buffers_;    Handler handler_;  };  // 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)  {    async_read_some_at(impl, 0, buffers, handler);  }  // 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)  {    if (!is_open(impl))    {      this->get_io_service().post(bind_handler(handler,            boost::asio::error::bad_descriptor, 0));      return;    }    // Update the ID of the thread from which cancellation is safe.    if (impl.safe_cancellation_thread_id_ == 0)      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())      impl.safe_cancellation_thread_id_ = ~DWORD(0);    // Allocate and construct an operation to wrap the handler.    typedef read_operation<MutableBufferSequence, Handler> value_type;    typedef handler_alloc_traits<Handler, value_type> alloc_traits;    raw_handler_ptr<alloc_traits> raw_ptr(handler);    handler_ptr<alloc_traits> ptr(raw_ptr, iocp_service_, buffers, handler);    // Find first buffer of non-zero length.    boost::asio::mutable_buffer buffer;    typename MutableBufferSequence::const_iterator iter = buffers.begin();    typename MutableBufferSequence::const_iterator end = buffers.end();    for (DWORD i = 0; iter != end; ++iter, ++i)    {      buffer = boost::asio::mutable_buffer(*iter);      if (boost::asio::buffer_size(buffer) != 0)        break;    }    // A request to receive 0 bytes on a stream handle is a no-op.    if (boost::asio::buffer_size(buffer) == 0)    {      boost::asio::io_service::work work(this->get_io_service());      ptr.reset();      boost::system::error_code error;      iocp_service_.post(bind_handler(handler, error, 0));      return;    }    // Read some data.    DWORD bytes_transferred = 0;    ptr.get()->Offset = offset & 0xFFFFFFFF;    ptr.get()->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;    BOOL ok = ::ReadFile(impl.handle_,        boost::asio::buffer_cast<LPVOID>(buffer),        static_cast<DWORD>(boost::asio::buffer_size(buffer)),        &bytes_transferred, ptr.get());    DWORD last_error = ::GetLastError();    if (!ok && last_error != ERROR_IO_PENDING)    {      boost::asio::io_service::work work(this->get_io_service());      ptr.reset();      boost::system::error_code ec(last_error,          boost::asio::error::get_system_category());      iocp_service_.post(bind_handler(handler, ec, bytes_transferred));    }    else    {      ptr.release();    }  }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 function to close a handle when the associated object is being  // destroyed.  void close_for_destruction(implementation_type& impl)  {    if (is_open(impl))    {      ::CloseHandle(impl.handle_);      impl.handle_ = INVALID_HANDLE_VALUE;      impl.safe_cancellation_thread_id_ = 0;    }  }  // 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.  boost::asio::detail::mutex mutex_;  // The head of a linked list of all implementations.  implementation_type* impl_list_;};} // namespace detail} // namespace asio} // namespace boost#endif // defined(BOOST_ASIO_HAS_IOCP)#include <boost/asio/detail/pop_options.hpp>#endif // BOOST_ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -