summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '3rdParty/Boost/src/boost/asio/detail/win_iocp_overlapped_ptr.hpp')
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/win_iocp_overlapped_ptr.hpp124
1 files changed, 44 insertions, 80 deletions
diff --git a/3rdParty/Boost/src/boost/asio/detail/win_iocp_overlapped_ptr.hpp b/3rdParty/Boost/src/boost/asio/detail/win_iocp_overlapped_ptr.hpp
index bb64014..082a5b1 100644
--- a/3rdParty/Boost/src/boost/asio/detail/win_iocp_overlapped_ptr.hpp
+++ b/3rdParty/Boost/src/boost/asio/detail/win_iocp_overlapped_ptr.hpp
@@ -21,8 +21,10 @@
#if defined(BOOST_ASIO_HAS_IOCP)
+#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/noncopyable.hpp>
#include <boost/asio/detail/win_iocp_io_service.hpp>
+#include <boost/asio/detail/win_iocp_operation.hpp>
namespace boost {
namespace asio {
@@ -35,7 +37,8 @@ class win_iocp_overlapped_ptr
public:
// Construct an empty win_iocp_overlapped_ptr.
win_iocp_overlapped_ptr()
- : ptr_(0)
+ : ptr_(0),
+ iocp_service_(0)
{
}
@@ -43,7 +46,8 @@ public:
template <typename Handler>
explicit win_iocp_overlapped_ptr(
boost::asio::io_service& io_service, Handler handler)
- : ptr_(0)
+ : ptr_(0),
+ iocp_service_(0)
{
this->reset(io_service, handler);
}
@@ -61,6 +65,8 @@ public:
{
ptr_->destroy();
ptr_ = 0;
+ iocp_service_->work_finished();
+ iocp_service_ = 0;
}
}
@@ -69,12 +75,14 @@ public:
template <typename Handler>
void reset(boost::asio::io_service& io_service, Handler handler)
{
- typedef overlapped_operation<Handler> value_type;
+ typedef overlapped_op<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, io_service.impl_, handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, handler);
+ io_service.impl_.work_started();
reset();
ptr_ = ptr.release();
+ iocp_service_ = &io_service.impl_;
}
// Get the contained OVERLAPPED object.
@@ -93,10 +101,11 @@ public:
OVERLAPPED* release()
{
if (ptr_)
- ptr_->on_pending();
+ iocp_service_->on_pending(ptr_);
OVERLAPPED* tmp = ptr_;
ptr_ = 0;
+ iocp_service_ = 0;
return tmp;
}
@@ -106,99 +115,54 @@ public:
{
if (ptr_)
{
- ptr_->ec_ = ec;
- ptr_->on_immediate_completion(0, static_cast<DWORD>(bytes_transferred));
+ iocp_service_->on_completion(ptr_, ec,
+ static_cast<DWORD>(bytes_transferred));
ptr_ = 0;
+ iocp_service_ = 0;
}
}
private:
- struct overlapped_operation_base
- : public win_iocp_io_service::operation
- {
- overlapped_operation_base(win_iocp_io_service& io_service,
- invoke_func_type invoke_func, destroy_func_type destroy_func)
- : win_iocp_io_service::operation(io_service, invoke_func, destroy_func),
- io_service_(io_service)
- {
- io_service_.work_started();
- }
-
- ~overlapped_operation_base()
- {
- io_service_.work_finished();
- }
-
- win_iocp_io_service& io_service_;
- boost::system::error_code ec_;
- };
-
template <typename Handler>
- struct overlapped_operation
- : public overlapped_operation_base
+ struct overlapped_op : public win_iocp_operation
{
- overlapped_operation(win_iocp_io_service& io_service,
- Handler handler)
- : overlapped_operation_base(io_service,
- &overlapped_operation<Handler>::do_completion_impl,
- &overlapped_operation<Handler>::destroy_impl),
+ overlapped_op(Handler handler)
+ : win_iocp_operation(&overlapped_op::do_complete),
handler_(handler)
{
}
- private:
- // Prevent copying and assignment.
- overlapped_operation(const overlapped_operation&);
- void operator=(const overlapped_operation&);
-
- static void do_completion_impl(win_iocp_io_service::operation* op,
- DWORD last_error, size_t bytes_transferred)
+ static void do_complete(io_service_impl* owner, operation* base,
+ boost::system::error_code ec, std::size_t bytes_transferred)
{
// Take ownership of the operation object.
- typedef overlapped_operation<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);
-
- // Make a copy of the handler and error_code so that the memory can be
- // deallocated before the upcall is made.
- Handler handler(handler_op->handler_);
- boost::system::error_code ec(handler_op->ec_);
- if (last_error)
- ec = boost::system::error_code(last_error,
- boost::asio::error::get_system_category());
-
- // Free the memory associated with the handler.
- ptr.reset();
-
- // Make the upcall.
- boost_asio_handler_invoke_helpers::invoke(
- bind_handler(handler, ec, bytes_transferred), handler);
- }
-
- static void destroy_impl(win_iocp_io_service::operation* op)
- {
- // Take ownership of the operation object.
- typedef overlapped_operation<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();
+ overlapped_op* o(static_cast<overlapped_op*>(base));
+ typedef handler_alloc_traits<Handler, overlapped_op> alloc_traits;
+ handler_ptr<alloc_traits> ptr(o->handler_, o);
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ // Make a copy of the handler so that the memory can be deallocated
+ // before the upcall is made. Even if we're not about to make an
+ // upcall, 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.
+ detail::binder2<Handler, boost::system::error_code, std::size_t>
+ handler(o->handler_, ec, bytes_transferred);
+ ptr.reset();
+ boost::asio::detail::fenced_block b;
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ }
}
+ private:
Handler handler_;
};
- overlapped_operation_base* ptr_;
+ win_iocp_operation* ptr_;
+ win_iocp_io_service* iocp_service_;
};
} // namespace detail