|
Boost-Commit : |
From: chris_at_[hidden]
Date: 2008-05-21 05:25:14
Author: chris_kohlhoff
Date: 2008-05-21 05:25:12 EDT (Wed, 21 May 2008)
New Revision: 45600
URL: http://svn.boost.org/trac/boost/changeset/45600
Log:
Implement custom allocation support for timer operations.
Text files modified:
trunk/boost/asio/detail/deadline_timer_service.hpp | 13 +++--
trunk/boost/asio/detail/dev_poll_reactor.hpp | 10 ++--
trunk/boost/asio/detail/epoll_reactor.hpp | 10 ++--
trunk/boost/asio/detail/kqueue_reactor.hpp | 10 ++--
trunk/boost/asio/detail/select_reactor.hpp | 10 ++--
trunk/boost/asio/detail/timer_queue.hpp | 89 ++++++++++++++++++++++++++-------------
trunk/boost/asio/detail/timer_queue_base.hpp | 4
trunk/boost/asio/detail/win_iocp_io_service.hpp | 2
8 files changed, 89 insertions(+), 59 deletions(-)
Modified: trunk/boost/asio/detail/deadline_timer_service.hpp
==============================================================================
--- trunk/boost/asio/detail/deadline_timer_service.hpp (original)
+++ trunk/boost/asio/detail/deadline_timer_service.hpp 2008-05-21 05:25:12 EDT (Wed, 21 May 2008)
@@ -26,6 +26,7 @@
#include <boost/asio/error.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/handler_base_from_member.hpp>
#include <boost/asio/detail/noncopyable.hpp>
#include <boost/asio/detail/service_base.hpp>
#include <boost/asio/detail/socket_ops.hpp>
@@ -154,25 +155,25 @@
}
template <typename Handler>
- class wait_handler
+ class wait_handler :
+ public handler_base_from_member<Handler>
{
public:
wait_handler(boost::asio::io_service& io_service, Handler handler)
- : io_service_(io_service),
- work_(io_service),
- handler_(handler)
+ : handler_base_from_member<Handler>(handler),
+ io_service_(io_service),
+ work_(io_service)
{
}
void operator()(const boost::system::error_code& result)
{
- io_service_.post(detail::bind_handler(handler_, result));
+ io_service_.post(detail::bind_handler(this->handler_, result));
}
private:
boost::asio::io_service& io_service_;
boost::asio::io_service::work work_;
- Handler handler_;
};
// Start an asynchronous wait on the timer.
Modified: trunk/boost/asio/detail/dev_poll_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/dev_poll_reactor.hpp (original)
+++ trunk/boost/asio/detail/dev_poll_reactor.hpp 2008-05-21 05:25:12 EDT (Wed, 21 May 2008)
@@ -340,7 +340,7 @@
// Check if the thread is supposed to stop.
if (stop_thread_)
{
- complete_operations_and_cleanup_timers(lock);
+ complete_operations_and_timers(lock);
return;
}
@@ -349,7 +349,7 @@
if (!block && read_op_queue_.empty() && write_op_queue_.empty()
&& except_op_queue_.empty() && all_timer_queues_are_empty())
{
- complete_operations_and_cleanup_timers(lock);
+ complete_operations_and_timers(lock);
return;
}
@@ -475,7 +475,7 @@
cancel_ops_unlocked(pending_cancellations_[i]);
pending_cancellations_.clear();
- complete_operations_and_cleanup_timers(lock);
+ complete_operations_and_timers(lock);
}
// Run the select loop in the thread.
@@ -575,7 +575,7 @@
// destructors may make calls back into this reactor. We make a copy of the
// vector of timer queues since the original may be modified while the lock
// is not held.
- void complete_operations_and_cleanup_timers(
+ void complete_operations_and_timers(
boost::asio::detail::mutex::scoped_lock& lock)
{
timer_queues_for_cleanup_ = timer_queues_;
@@ -584,7 +584,7 @@
write_op_queue_.complete_operations();
except_op_queue_.complete_operations();
for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i)
- timer_queues_for_cleanup_[i]->cleanup_timers();
+ timer_queues_for_cleanup_[i]->complete_timers();
}
// Add a pending event entry for the given descriptor.
Modified: trunk/boost/asio/detail/epoll_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/epoll_reactor.hpp (original)
+++ trunk/boost/asio/detail/epoll_reactor.hpp 2008-05-21 05:25:12 EDT (Wed, 21 May 2008)
@@ -436,7 +436,7 @@
// Check if the thread is supposed to stop.
if (stop_thread_)
{
- complete_operations_and_cleanup_timers(lock);
+ complete_operations_and_timers(lock);
return;
}
@@ -445,7 +445,7 @@
if (!block && read_op_queue_.empty() && write_op_queue_.empty()
&& except_op_queue_.empty() && all_timer_queues_are_empty())
{
- complete_operations_and_cleanup_timers(lock);
+ complete_operations_and_timers(lock);
return;
}
@@ -552,7 +552,7 @@
need_epoll_wait_ = !read_op_queue_.empty()
|| !write_op_queue_.empty() || !except_op_queue_.empty();
- complete_operations_and_cleanup_timers(lock);
+ complete_operations_and_timers(lock);
}
// Run the select loop in the thread.
@@ -655,7 +655,7 @@
// destructors may make calls back into this reactor. We make a copy of the
// vector of timer queues since the original may be modified while the lock
// is not held.
- void complete_operations_and_cleanup_timers(
+ void complete_operations_and_timers(
boost::asio::detail::mutex::scoped_lock& lock)
{
timer_queues_for_cleanup_ = timer_queues_;
@@ -664,7 +664,7 @@
write_op_queue_.complete_operations();
except_op_queue_.complete_operations();
for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i)
- timer_queues_for_cleanup_[i]->cleanup_timers();
+ timer_queues_for_cleanup_[i]->complete_timers();
}
// Mutex to protect access to internal data.
Modified: trunk/boost/asio/detail/kqueue_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/kqueue_reactor.hpp (original)
+++ trunk/boost/asio/detail/kqueue_reactor.hpp 2008-05-21 05:25:12 EDT (Wed, 21 May 2008)
@@ -403,7 +403,7 @@
// Check if the thread is supposed to stop.
if (stop_thread_)
{
- complete_operations_and_cleanup_timers(lock);
+ complete_operations_and_timers(lock);
return;
}
@@ -412,7 +412,7 @@
if (!block && read_op_queue_.empty() && write_op_queue_.empty()
&& except_op_queue_.empty() && all_timer_queues_are_empty())
{
- complete_operations_and_cleanup_timers(lock);
+ complete_operations_and_timers(lock);
return;
}
@@ -536,7 +536,7 @@
need_kqueue_wait_ = !read_op_queue_.empty()
|| !write_op_queue_.empty() || !except_op_queue_.empty();
- complete_operations_and_cleanup_timers(lock);
+ complete_operations_and_timers(lock);
}
// Run the select loop in the thread.
@@ -637,7 +637,7 @@
// destructors may make calls back into this reactor. We make a copy of the
// vector of timer queues since the original may be modified while the lock
// is not held.
- void complete_operations_and_cleanup_timers(
+ void complete_operations_and_timers(
boost::asio::detail::mutex::scoped_lock& lock)
{
timer_queues_for_cleanup_ = timer_queues_;
@@ -646,7 +646,7 @@
write_op_queue_.complete_operations();
except_op_queue_.complete_operations();
for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i)
- timer_queues_for_cleanup_[i]->cleanup_timers();
+ timer_queues_for_cleanup_[i]->complete_timers();
}
// Mutex to protect access to internal data.
Modified: trunk/boost/asio/detail/select_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/select_reactor.hpp (original)
+++ trunk/boost/asio/detail/select_reactor.hpp 2008-05-21 05:25:12 EDT (Wed, 21 May 2008)
@@ -320,7 +320,7 @@
// Check if the thread is supposed to stop.
if (stop_thread_)
{
- complete_operations_and_cleanup_timers(lock);
+ complete_operations_and_timers(lock);
return;
}
@@ -329,7 +329,7 @@
if (!block && read_op_queue_.empty() && write_op_queue_.empty()
&& except_op_queue_.empty() && all_timer_queues_are_empty())
{
- complete_operations_and_cleanup_timers(lock);
+ complete_operations_and_timers(lock);
return;
}
@@ -392,7 +392,7 @@
cancel_ops_unlocked(pending_cancellations_[i]);
pending_cancellations_.clear();
- complete_operations_and_cleanup_timers(lock);
+ complete_operations_and_timers(lock);
}
// Run the select loop in the thread.
@@ -477,7 +477,7 @@
// destructors may make calls back into this reactor. We make a copy of the
// vector of timer queues since the original may be modified while the lock
// is not held.
- void complete_operations_and_cleanup_timers(
+ void complete_operations_and_timers(
boost::asio::detail::mutex::scoped_lock& lock)
{
timer_queues_for_cleanup_ = timer_queues_;
@@ -486,7 +486,7 @@
write_op_queue_.complete_operations();
except_op_queue_.complete_operations();
for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i)
- timer_queues_for_cleanup_[i]->cleanup_timers();
+ timer_queues_for_cleanup_[i]->complete_timers();
}
// Mutex to protect access to internal data.
Modified: trunk/boost/asio/detail/timer_queue.hpp
==============================================================================
--- trunk/boost/asio/detail/timer_queue.hpp (original)
+++ trunk/boost/asio/detail/timer_queue.hpp 2008-05-21 05:25:12 EDT (Wed, 21 May 2008)
@@ -27,6 +27,7 @@
#include <boost/asio/detail/pop_options.hpp>
#include <boost/asio/error.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/hash_map.hpp>
#include <boost/asio/detail/noncopyable.hpp>
#include <boost/asio/detail/timer_queue_base.hpp>
@@ -51,7 +52,7 @@
: timers_(),
heap_(),
cancelled_timers_(0),
- cleanup_timers_(0)
+ complete_timers_(0)
{
}
@@ -116,10 +117,10 @@
{
timer_base* t = heap_[0];
remove_timer(t);
+ t->result_ = boost::system::error_code();
t->prev_ = 0;
- t->next_ = cleanup_timers_;
- cleanup_timers_ = t;
- t->invoke(boost::system::error_code());
+ t->next_ = complete_timers_;
+ complete_timers_ = t;
}
}
@@ -155,17 +156,23 @@
while (cancelled_timers_)
{
timer_base* this_timer = cancelled_timers_;
+ this_timer->result_ = boost::asio::error::operation_aborted;
cancelled_timers_ = this_timer->next_;
- this_timer->next_ = cleanup_timers_;
- cleanup_timers_ = this_timer;
- this_timer->invoke(boost::asio::error::operation_aborted);
+ this_timer->next_ = complete_timers_;
+ complete_timers_ = this_timer;
}
}
- // Destroy timers that are waiting to be cleaned up.
- virtual void cleanup_timers()
+ // Complete any timers that are waiting to be completed.
+ virtual void complete_timers()
{
- destroy_timer_list(cleanup_timers_);
+ while (complete_timers_)
+ {
+ timer_base* this_timer = complete_timers_;
+ complete_timers_ = this_timer->next_;
+ this_timer->next_ = 0;
+ this_timer->complete();
+ }
}
// Destroy all timers.
@@ -183,7 +190,7 @@
heap_.clear();
timers_.clear();
destroy_timer_list(cancelled_timers_);
- destroy_timer_list(cleanup_timers_);
+ destroy_timer_list(complete_timers_);
}
private:
@@ -192,27 +199,27 @@
class timer_base
{
public:
- // Perform the timer operation and then destroy.
- void invoke(const boost::system::error_code& result)
+ // Delete the timer and post the handler.
+ void complete()
{
- invoke_func_(this, result);
+ complete_func_(this, result_);
}
- // Destroy the timer operation.
+ // Delete the timer.
void destroy()
{
destroy_func_(this);
}
protected:
- typedef void (*invoke_func_type)(timer_base*,
+ typedef void (*complete_func_type)(timer_base*,
const boost::system::error_code&);
typedef void (*destroy_func_type)(timer_base*);
// Constructor.
- timer_base(invoke_func_type invoke_func, destroy_func_type destroy_func,
+ timer_base(complete_func_type complete_func, destroy_func_type destroy_func,
const time_type& time, void* token)
- : invoke_func_(invoke_func),
+ : complete_func_(complete_func),
destroy_func_(destroy_func),
time_(time),
token_(token),
@@ -231,13 +238,16 @@
private:
friend class timer_queue<Time_Traits>;
- // The function to be called to dispatch the handler.
- invoke_func_type invoke_func_;
+ // The function to be called to delete the timer and post the handler.
+ complete_func_type complete_func_;
- // The function to be called to destroy the handler.
+ // The function to be called to delete the timer.
destroy_func_type destroy_func_;
- // The time when the operation should fire.
+ // The result of the timer operation.
+ boost::system::error_code result_;
+
+ // The time when the timer should fire.
time_type time_;
// The token associated with the timer.
@@ -261,23 +271,42 @@
public:
// Constructor.
timer(const time_type& time, Handler handler, void* token)
- : timer_base(&timer<Handler>::invoke_handler,
+ : timer_base(&timer<Handler>::complete_handler,
&timer<Handler>::destroy_handler, time, token),
handler_(handler)
{
}
- // Invoke the handler and then destroy it.
- static void invoke_handler(timer_base* base,
+ // Delete the timer and post the handler.
+ static void complete_handler(timer_base* base,
const boost::system::error_code& result)
{
- static_cast<timer<Handler>*>(base)->handler_(result);
+ // Take ownership of the timer object.
+ typedef timer<Handler> this_type;
+ this_type* this_timer(static_cast<this_type*>(base));
+ typedef handler_alloc_traits<Handler, this_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(this_timer->handler_, this_timer);
+
+ // Make a copy of the error_code and the handler so that the memory can
+ // be deallocated before the upcall is made.
+ boost::system::error_code ec(result);
+ Handler handler(this_timer->handler_);
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+
+ // Make the upcall.
+ handler(ec);
}
- // Destroy the handler.
+ // Delete the timer.
static void destroy_handler(timer_base* base)
{
- delete static_cast<timer<Handler>*>(base);
+ // Take ownership of the timer object.
+ typedef timer<Handler> this_type;
+ this_type* this_timer(static_cast<this_type*>(base));
+ typedef handler_alloc_traits<Handler, this_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(this_timer->handler_, this_timer);
}
private:
@@ -386,8 +415,8 @@
// The list of timers to be cancelled.
timer_base* cancelled_timers_;
- // The list of timers to be destroyed.
- timer_base* cleanup_timers_;
+ // The list of timers waiting to be completed.
+ timer_base* complete_timers_;
};
} // namespace detail
Modified: trunk/boost/asio/detail/timer_queue_base.hpp
==============================================================================
--- trunk/boost/asio/detail/timer_queue_base.hpp (original)
+++ trunk/boost/asio/detail/timer_queue_base.hpp 2008-05-21 05:25:12 EDT (Wed, 21 May 2008)
@@ -48,8 +48,8 @@
// Dispatch any pending cancels for timers.
virtual void dispatch_cancellations() = 0;
- // Destroy timers that are waiting to be cleaned up.
- virtual void cleanup_timers() = 0;
+ // Complete all timers that are waiting to be completed.
+ virtual void complete_timers() = 0;
// Destroy all timers.
virtual void destroy_timers() = 0;
Modified: trunk/boost/asio/detail/win_iocp_io_service.hpp
==============================================================================
--- trunk/boost/asio/detail/win_iocp_io_service.hpp (original)
+++ trunk/boost/asio/detail/win_iocp_io_service.hpp 2008-05-21 05:25:12 EDT (Wed, 21 May 2008)
@@ -436,7 +436,7 @@
{
timer_queues_copy_[i]->dispatch_timers();
timer_queues_copy_[i]->dispatch_cancellations();
- timer_queues_copy_[i]->cleanup_timers();
+ timer_queues_copy_[i]->complete_timers();
}
}
catch (...)
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk