diff options
Diffstat (limited to '3rdParty/Boost/src/boost/asio/detail/win_iocp_io_service.hpp')
-rw-r--r-- | 3rdParty/Boost/src/boost/asio/detail/win_iocp_io_service.hpp | 88 |
1 files changed, 62 insertions, 26 deletions
diff --git a/3rdParty/Boost/src/boost/asio/detail/win_iocp_io_service.hpp b/3rdParty/Boost/src/boost/asio/detail/win_iocp_io_service.hpp index 5818542..1dfb9a1 100644 --- a/3rdParty/Boost/src/boost/asio/detail/win_iocp_io_service.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/win_iocp_io_service.hpp @@ -2,7 +2,7 @@ // win_iocp_io_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2010 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) @@ -22,7 +22,7 @@ #if defined(BOOST_ASIO_HAS_IOCP) #include <boost/asio/detail/push_options.hpp> -#include <limits> +#include <boost/limits.hpp> #include <boost/throw_exception.hpp> #include <boost/system/system_error.hpp> #include <boost/asio/detail/pop_options.hpp> @@ -50,6 +50,8 @@ public: // This class inherits from OVERLAPPED so that we can downcast to get back to // the operation pointer from the LPOVERLAPPED out parameter of // GetQueuedCompletionStatus. + class operation; + friend class operation; class operation : public OVERLAPPED { @@ -59,7 +61,10 @@ public: operation(win_iocp_io_service& iocp_service, invoke_func_type invoke_func, destroy_func_type destroy_func) - : outstanding_operations_(&iocp_service.outstanding_operations_), + : iocp_service_(iocp_service), + ready_(0), + last_error_(~DWORD(0)), + bytes_transferred_(0), invoke_func_(invoke_func), destroy_func_(destroy_func) { @@ -69,12 +74,48 @@ public: OffsetHigh = 0; hEvent = 0; - ::InterlockedIncrement(outstanding_operations_); + ::InterlockedIncrement(&iocp_service_.outstanding_operations_); + } + + void reset() + { + Internal = 0; + InternalHigh = 0; + Offset = 0; + OffsetHigh = 0; + hEvent = 0; + ready_ = 0; + last_error_ = ~DWORD(0); + bytes_transferred_ = 0; + } + + void on_pending() + { + if (::InterlockedCompareExchange(&ready_, 1, 0) == 1) + iocp_service_.post_completion(this, last_error_, bytes_transferred_); } - void do_completion(DWORD last_error, size_t bytes_transferred) + void on_immediate_completion(DWORD last_error, DWORD bytes_transferred) { - invoke_func_(this, last_error, bytes_transferred); + ready_ = 1; + iocp_service_.post_completion(this, last_error, bytes_transferred); + } + + bool on_completion(DWORD last_error, DWORD bytes_transferred) + { + if (last_error_ == ~DWORD(0)) + { + last_error_ = last_error; + bytes_transferred_ = bytes_transferred; + } + + if (::InterlockedCompareExchange(&ready_, 1, 0) == 1) + { + invoke_func_(this, last_error_, bytes_transferred_); + return true; + } + + return false; } void destroy() @@ -86,16 +127,18 @@ public: // Prevent deletion through this type. ~operation() { - ::InterlockedDecrement(outstanding_operations_); + ::InterlockedDecrement(&iocp_service_.outstanding_operations_); } private: - long* outstanding_operations_; + win_iocp_io_service& iocp_service_; + long ready_; + DWORD last_error_; + DWORD bytes_transferred_; invoke_func_type invoke_func_; destroy_func_type destroy_func_; }; - // Constructor. win_iocp_io_service(boost::asio::io_service& io_service) : boost::asio::detail::service_base<win_iocp_io_service>(io_service), @@ -132,7 +175,7 @@ public: while (::InterlockedExchangeAdd(&outstanding_operations_, 0) > 0) { DWORD bytes_transferred = 0; -#if (WINVER < 0x0500) +#if defined(WINVER) && (WINVER < 0x0500) DWORD completion_key = 0; #else DWORD_PTR completion_key = 0; @@ -276,7 +319,7 @@ public: void dispatch(Handler handler) { if (call_stack<win_iocp_io_service>::contains(this)) - boost_asio_handler_invoke_helpers::invoke(handler, &handler); + boost_asio_handler_invoke_helpers::invoke(handler, handler); else post(handler); } @@ -296,15 +339,7 @@ public: handler_ptr<alloc_traits> ptr(raw_ptr, *this, handler); // Enqueue the operation on the I/O completion port. - if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, ptr.get())) - { - DWORD last_error = ::GetLastError(); - boost::system::system_error e( - boost::system::error_code(last_error, - boost::asio::error::get_system_category()), - "pqcs"); - boost::throw_exception(e); - } + ptr.get()->on_immediate_completion(0, 0); // Operation has been successfully posted. ptr.release(); @@ -419,7 +454,7 @@ private: // Get the next operation from the queue. DWORD bytes_transferred = 0; -#if (WINVER < 0x0500) +#if defined(WINVER) && (WINVER < 0x0500) DWORD completion_key = 0; #else DWORD_PTR completion_key = 0; @@ -507,10 +542,11 @@ private: // Dispatch the operation. operation* op = static_cast<operation*>(overlapped); - op->do_completion(last_error, bytes_transferred); - - ec = boost::system::error_code(); - return 1; + if (op->on_completion(last_error, bytes_transferred)) + { + ec = boost::system::error_code(); + return 1; + } } else if (completion_key == transfer_timer_dispatching) { @@ -648,7 +684,7 @@ private: ptr.reset(); // Make the upcall. - boost_asio_handler_invoke_helpers::invoke(handler, &handler); + boost_asio_handler_invoke_helpers::invoke(handler, handler); } static void destroy_impl(operation* op) |