summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
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.hpp88
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)