Skip to content

Instantly share code, notes, and snippets.

@Jackarain
Created June 29, 2013 07:11
Show Gist options
  • Save Jackarain/5890195 to your computer and use it in GitHub Desktop.
Save Jackarain/5890195 to your computer and use it in GitHub Desktop.
From 81a6a51c0cb66de6bc77e1fa5dcd46b2794995e4 Mon Sep 17 00:00:00 2001
From: Christopher Kohlhoff <[email protected]>
Date: Wed, 23 Mar 2011 15:03:56 +1100
Subject: [PATCH] On Windows, ensure the count of outstanding work is decremented for
abandoned operations (i.e. operations that are being cleaned up within
the io_service destructor).
---
asio/include/asio/detail/impl/dev_poll_reactor.ipp | 2 ++
asio/include/asio/detail/impl/epoll_reactor.ipp | 2 ++
asio/include/asio/detail/impl/kqueue_reactor.ipp | 2 ++
asio/include/asio/detail/impl/select_reactor.ipp | 2 ++
.../asio/detail/impl/signal_set_service.ipp | 2 ++
asio/include/asio/detail/impl/task_io_service.ipp | 7 +++++++
.../asio/detail/impl/win_iocp_io_service.ipp | 11 +++++++++++
asio/include/asio/detail/task_io_service.hpp | 4 ++++
asio/include/asio/detail/win_iocp_io_service.hpp | 4 ++++
9 files changed, 36 insertions(+), 0 deletions(-)
diff --git a/asio/include/asio/detail/impl/dev_poll_reactor.ipp b/asio/include/asio/detail/impl/dev_poll_reactor.ipp
index 06d89ea..2a01993 100644
--- a/asio/include/asio/detail/impl/dev_poll_reactor.ipp
+++ b/asio/include/asio/detail/impl/dev_poll_reactor.ipp
@@ -63,6 +63,8 @@ void dev_poll_reactor::shutdown_service()
op_queue_[i].get_all_operations(ops);
timer_queues_.get_all_timers(ops);
+
+ io_service_.abandon_operations(ops);
}
// Helper class to re-register all descriptors with /dev/poll.
diff --git a/asio/include/asio/detail/impl/epoll_reactor.ipp b/asio/include/asio/detail/impl/epoll_reactor.ipp
index 22f567a..d08dedb 100644
--- a/asio/include/asio/detail/impl/epoll_reactor.ipp
+++ b/asio/include/asio/detail/impl/epoll_reactor.ipp
@@ -84,6 +84,8 @@ void epoll_reactor::shutdown_service()
}
timer_queues_.get_all_timers(ops);
+
+ io_service_.abandon_operations(ops);
}
void epoll_reactor::fork_service(asio::io_service::fork_event fork_ev)
diff --git a/asio/include/asio/detail/impl/kqueue_reactor.ipp b/asio/include/asio/detail/impl/kqueue_reactor.ipp
index f0cdf73..45aff60 100644
--- a/asio/include/asio/detail/impl/kqueue_reactor.ipp
+++ b/asio/include/asio/detail/impl/kqueue_reactor.ipp
@@ -74,6 +74,8 @@ void kqueue_reactor::shutdown_service()
}
timer_queues_.get_all_timers(ops);
+
+ io_service_.abandon_operations(ops);
}
void kqueue_reactor::fork_service(asio::io_service::fork_event fork_ev)
diff --git a/asio/include/asio/detail/impl/select_reactor.ipp b/asio/include/asio/detail/impl/select_reactor.ipp
index f4e0314..00fd9fc 100644
--- a/asio/include/asio/detail/impl/select_reactor.ipp
+++ b/asio/include/asio/detail/impl/select_reactor.ipp
@@ -81,6 +81,8 @@ void select_reactor::shutdown_service()
op_queue_[i].get_all_operations(ops);
timer_queues_.get_all_timers(ops);
+
+ io_service_.abandon_operations(ops);
}
void select_reactor::fork_service(asio::io_service::fork_event fork_ev)
diff --git a/asio/include/asio/detail/impl/signal_set_service.ipp b/asio/include/asio/detail/impl/signal_set_service.ipp
index f0f0e78..4cde184 100644
--- a/asio/include/asio/detail/impl/signal_set_service.ipp
+++ b/asio/include/asio/detail/impl/signal_set_service.ipp
@@ -145,6 +145,8 @@ void signal_set_service::shutdown_service()
reg = reg->next_in_table_;
}
}
+
+ io_service_.abandon_operations(ops);
}
void signal_set_service::fork_service(
diff --git a/asio/include/asio/detail/impl/task_io_service.ipp b/asio/include/asio/detail/impl/task_io_service.ipp
index cb585d5..0a2c6fa 100644
--- a/asio/include/asio/detail/impl/task_io_service.ipp
+++ b/asio/include/asio/detail/impl/task_io_service.ipp
@@ -230,6 +230,13 @@ void task_io_service::post_deferred_completions(
}
}
+void task_io_service::abandon_operations(
+ op_queue<task_io_service::operation>& ops)
+{
+ op_queue<task_io_service::operation> ops2;
+ ops2.push(ops);
+}
+
std::size_t task_io_service::do_one(mutex::scoped_lock& lock,
task_io_service::idle_thread_info* this_idle_thread)
{
diff --git a/asio/include/asio/detail/impl/win_iocp_io_service.ipp b/asio/include/asio/detail/impl/win_iocp_io_service.ipp
index ca3125e..7aaa6b8 100644
--- a/asio/include/asio/detail/impl/win_iocp_io_service.ipp
+++ b/asio/include/asio/detail/impl/win_iocp_io_service.ipp
@@ -262,6 +262,17 @@ void win_iocp_io_service::post_deferred_completions(
}
}
+void win_iocp_io_service::abandon_operations(
+ op_queue<win_iocp_operation>& ops)
+{
+ while (win_iocp_operation* op = ops.front())
+ {
+ ops.pop();
+ ::InterlockedDecrement(&outstanding_work_);
+ op->destroy();
+ }
+}
+
void win_iocp_io_service::on_pending(win_iocp_operation* op)
{
if (::InterlockedCompareExchange(&op->ready_, 1, 0) == 1)
diff --git a/asio/include/asio/detail/task_io_service.hpp b/asio/include/asio/detail/task_io_service.hpp
index 285d83e..654f83c 100644
--- a/asio/include/asio/detail/task_io_service.hpp
+++ b/asio/include/asio/detail/task_io_service.hpp
@@ -105,6 +105,10 @@ public:
// that work_started() was previously called for each operation.
ASIO_DECL void post_deferred_completions(op_queue<operation>& ops);
+ // Process unfinished operations as part of a shutdown_service operation.
+ // Assumes that work_started() was previously called for the operations.
+ ASIO_DECL void abandon_operations(op_queue<operation>& ops);
+
private:
// Structure containing information about an idle thread.
struct idle_thread_info;
diff --git a/asio/include/asio/detail/win_iocp_io_service.hpp b/asio/include/asio/detail/win_iocp_io_service.hpp
index a562834..b5d7f0b 100644
--- a/asio/include/asio/detail/win_iocp_io_service.hpp
+++ b/asio/include/asio/detail/win_iocp_io_service.hpp
@@ -126,6 +126,10 @@ public:
ASIO_DECL void post_deferred_completions(
op_queue<win_iocp_operation>& ops);
+ // Enqueue unfinished operation as part of a shutdown_service operation.
+ // Assumes that work_started() was previously called for the operations.
+ ASIO_DECL void abandon_operations(op_queue<operation>& ops);
+
// Called after starting an overlapped I/O operation that did not complete
// immediately. The caller must have already called work_started() prior to
// starting the operation.
--
1.7.0.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment