$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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 (...)