$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: chris_at_[hidden]
Date: 2007-09-20 18:26:55
Author: chris_kohlhoff
Date: 2007-09-20 18:26:55 EDT (Thu, 20 Sep 2007)
New Revision: 39430
URL: http://svn.boost.org/trac/boost/changeset/39430
Log:
Move handler queue management to a separate class.
Added:
   trunk/boost/asio/detail/handler_queue.hpp   (contents, props changed)
Text files modified: 
   trunk/boost/asio/detail/task_io_service.hpp |   154 ++++----------------------------------- 
   1 files changed, 18 insertions(+), 136 deletions(-)
Added: trunk/boost/asio/detail/handler_queue.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/detail/handler_queue.hpp	2007-09-20 18:26:55 EDT (Thu, 20 Sep 2007)
@@ -0,0 +1,221 @@
+//
+// handler_queue.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2007 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)
+//
+
+#ifndef BOOST_ASIO_DETAIL_HANDLER_QUEUE_HPP
+#define BOOST_ASIO_DETAIL_HANDLER_QUEUE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class handler_queue
+  : noncopyable
+{
+public:
+  // Base class for handlers in the queue.
+  class handler
+    : private noncopyable
+  {
+  public:
+    void invoke()
+    {
+      invoke_func_(this);
+    }
+
+    void destroy()
+    {
+      destroy_func_(this);
+    }
+
+  protected:
+    typedef void (*invoke_func_type)(handler*);
+    typedef void (*destroy_func_type)(handler*);
+
+    handler(invoke_func_type invoke_func,
+        destroy_func_type destroy_func)
+      : next_(0),
+        invoke_func_(invoke_func),
+        destroy_func_(destroy_func)
+    {
+    }
+
+    ~handler()
+    {
+    }
+
+  private:
+    friend class handler_queue;
+    handler* next_;
+    invoke_func_type invoke_func_;
+    destroy_func_type destroy_func_;
+  };
+
+  // Smart point to manager handler lifetimes.
+  class scoped_ptr
+    : noncopyable
+  {
+  public:
+    explicit scoped_ptr(handler* h)
+      : handler_(h)
+    {
+    }
+
+    ~scoped_ptr()
+    {
+      if (handler_)
+        handler_->destroy();
+    }
+
+    handler* get() const
+    {
+      return handler_;
+    }
+
+    handler* release()
+    {
+      handler* tmp = handler_;
+      handler_ = 0;
+      return tmp;
+    }
+
+  private:
+    handler* handler_;
+  };
+
+  // Constructor.
+  handler_queue()
+    : front_(0),
+      back_(0)
+  {
+  }
+
+  // Wrap a handler to be pushed into the queue.
+  template <typename Handler>
+  static handler* wrap(Handler h)
+  {
+    // Allocate and construct an object to wrap the handler.
+    typedef handler_wrapper<Handler> value_type;
+    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+    raw_handler_ptr<alloc_traits> raw_ptr(h);
+    handler_ptr<alloc_traits> ptr(raw_ptr, h);
+    return ptr.release();
+  }
+
+  // Get the handler at the front of the queue.
+  handler* front()
+  {
+    return front_;
+  }
+
+  // Pop a handler from the front of the queue.
+  void pop()
+  {
+    if (front_)
+    {
+      handler* tmp = front_;
+      front_ = front_->next_;
+      if (front_ == 0)
+        back_ = 0;
+      tmp->next_= 0;
+    }
+  }
+
+  // Push a handler on to the back of the queue.
+  void push(handler* h)
+  {
+    h->next_ = 0;
+    if (back_)
+    {
+      back_->next_ = h;
+      back_ = h;
+    }
+    else
+    {
+      front_ = back_ = h;
+    }
+  }
+
+  // Whether the queue is empty.
+  bool empty() const
+  {
+    return front_ == 0;
+  }
+
+private:
+  // Template wrapper for handlers.
+  template <typename Handler>
+  class handler_wrapper
+    : public handler
+  {
+  public:
+    handler_wrapper(Handler h)
+      : handler(
+          &handler_wrapper<Handler>::do_call,
+          &handler_wrapper<Handler>::do_destroy),
+        handler_(h)
+    {
+    }
+
+    static void do_call(handler* base)
+    {
+      // Take ownership of the handler object.
+      typedef handler_wrapper<Handler> this_type;
+      this_type* h(static_cast<this_type*>(base));
+      typedef handler_alloc_traits<Handler, this_type> alloc_traits;
+      handler_ptr<alloc_traits> ptr(h->handler_, h);
+
+      // Make a copy of the handler so that the memory can be deallocated before
+      // the upcall is made.
+      Handler handler(h->handler_);
+
+      // Free the memory associated with the handler.
+      ptr.reset();
+
+      // Make the upcall.
+      asio_handler_invoke_helpers::invoke(handler, &handler);
+    }
+
+    static void do_destroy(handler* base)
+    {
+      // Take ownership of the handler object.
+      typedef handler_wrapper<Handler> this_type;
+      this_type* h(static_cast<this_type*>(base));
+      typedef handler_alloc_traits<Handler, this_type> alloc_traits;
+      handler_ptr<alloc_traits> ptr(h->handler_, h);
+    }
+
+  private:
+    Handler handler_;
+  };
+
+  // The front of the queue.
+  handler* front_;
+
+  // The back of the queue.
+  handler* back_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_HANDLER_QUEUE_HPP
Modified: trunk/boost/asio/detail/task_io_service.hpp
==============================================================================
--- trunk/boost/asio/detail/task_io_service.hpp	(original)
+++ trunk/boost/asio/detail/task_io_service.hpp	2007-09-20 18:26:55 EDT (Thu, 20 Sep 2007)
@@ -22,6 +22,7 @@
 #include <boost/asio/detail/event.hpp>
 #include <boost/asio/detail/handler_alloc_helpers.hpp>
 #include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/handler_queue.hpp>
 #include <boost/asio/detail/mutex.hpp>
 #include <boost/asio/detail/service_base.hpp>
 #include <boost/asio/detail/task_io_service_fwd.hpp>
@@ -42,12 +43,11 @@
       task_(use_service<Task>(io_service)),
       task_interrupted_(true),
       outstanding_work_(0),
-      handler_queue_(&task_handler_),
-      handler_queue_end_(&task_handler_),
       stopped_(false),
       shutdown_(false),
       first_idle_thread_(0)
   {
+    handler_queue_.push(&task_handler_);
   }
 
   void init(size_t /*concurrency_hint*/)
@@ -62,17 +62,16 @@
     lock.unlock();
 
     // Destroy handler objects.
-    while (handler_queue_)
+    while (!handler_queue_.empty())
     {
-      handler_base* h = handler_queue_;
-      handler_queue_ = h->next_;
+      handler_queue::handler* h = handler_queue_.front();
+      handler_queue_.pop();
       if (h != &task_handler_)
         h->destroy();
     }
 
     // Reset handler queue to initial state.
-    handler_queue_ = &task_handler_;
-    handler_queue_end_ = &task_handler_;
+    handler_queue_.push(&task_handler_);
   }
 
   // Run the event loop until interrupted or no more work.
@@ -173,10 +172,7 @@
   void post(Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef handler_wrapper<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, handler);
+    handler_queue::scoped_ptr ptr(handler_queue::wrap(handler));
 
     boost::asio::detail::mutex::scoped_lock lock(mutex_);
 
@@ -185,15 +181,7 @@
       return;
 
     // Add the handler to the end of the queue.
-    if (handler_queue_end_)
-    {
-      handler_queue_end_->next_ = ptr.get();
-      handler_queue_end_ = ptr.get();
-    }
-    else
-    {
-      handler_queue_ = handler_queue_end_ = ptr.get();
-    }
+    handler_queue_.push(ptr.get());
     ptr.release();
 
     // An undelivered handler is treated as unfinished work.
@@ -227,18 +215,15 @@
     bool task_has_run = false;
     while (!stopped_)
     {
-      if (handler_queue_)
+      if (!handler_queue_.empty())
       {
         // Prepare to execute first handler from queue.
-        handler_base* h = handler_queue_;
-        handler_queue_ = h->next_;
-        if (handler_queue_ == 0)
-          handler_queue_end_ = 0;
-        h->next_ = 0;
+        handler_queue::handler* h = handler_queue_.front();
+        handler_queue_.pop();
 
         if (h == &task_handler_)
         {
-          bool more_handlers = (handler_queue_ != 0);
+          bool more_handlers = (!handler_queue_.empty());
           task_interrupted_ = more_handlers || polling;
           lock.unlock();
 
@@ -263,7 +248,7 @@
           handler_cleanup c(lock, *this);
 
           // Invoke the handler. May throw an exception.
-          h->call(); // call() deletes the handler object
+          h->invoke(); // invoke() deletes the handler object
 
           ec = boost::system::error_code();
           return 1;
@@ -330,93 +315,6 @@
     }
   }
 
-  class task_cleanup;
-  friend class task_cleanup;
-
-  // The base class for all handler wrappers. A function pointer is used
-  // instead of virtual functions to avoid the associated overhead.
-  class handler_base
-  {
-  public:
-    typedef void (*call_func_type)(handler_base*);
-    typedef void (*destroy_func_type)(handler_base*);
-
-    handler_base(call_func_type call_func, destroy_func_type destroy_func)
-      : next_(0),
-        call_func_(call_func),
-        destroy_func_(destroy_func)
-    {
-    }
-
-    void call()
-    {
-      call_func_(this);
-    }
-
-    void destroy()
-    {
-      destroy_func_(this);
-    }
-
-  protected:
-    // Prevent deletion through this type.
-    ~handler_base()
-    {
-    }
-
-  private:
-    friend class task_io_service<Task>;
-    friend class task_cleanup;
-    handler_base* next_;
-    call_func_type call_func_;
-    destroy_func_type destroy_func_;
-  };
-
-  // Template wrapper for handlers.
-  template <typename Handler>
-  class handler_wrapper
-    : public handler_base
-  {
-  public:
-    handler_wrapper(Handler handler)
-      : handler_base(&handler_wrapper<Handler>::do_call,
-          &handler_wrapper<Handler>::do_destroy),
-        handler_(handler)
-    {
-    }
-
-    static void do_call(handler_base* base)
-    {
-      // Take ownership of the handler object.
-      typedef handler_wrapper<Handler> this_type;
-      this_type* h(static_cast<this_type*>(base));
-      typedef handler_alloc_traits<Handler, this_type> alloc_traits;
-      handler_ptr<alloc_traits> ptr(h->handler_, h);
-
-      // Make a copy of the handler so that the memory can be deallocated before
-      // the upcall is made.
-      Handler handler(h->handler_);
-
-      // Free the memory associated with the handler.
-      ptr.reset();
-
-      // Make the upcall.
-      asio_handler_invoke_helpers::invoke(handler, &handler);
-    }
-
-    static void do_destroy(handler_base* base)
-    {
-      // Take ownership of the handler object.
-      typedef handler_wrapper<Handler> this_type;
-      this_type* h(static_cast<this_type*>(base));
-      typedef handler_alloc_traits<Handler, this_type> alloc_traits;
-      handler_ptr<alloc_traits> ptr(h->handler_, h);
-    }
-
-  private:
-    Handler handler_;
-  };
-
   // Helper class to perform task-related operations on block exit.
   class task_cleanup
   {
@@ -433,20 +331,7 @@
       // Reinsert the task at the end of the handler queue.
       lock_.lock();
       task_io_service_.task_interrupted_ = true;
-      task_io_service_.task_handler_.next_ = 0;
-      if (task_io_service_.handler_queue_end_)
-      {
-        task_io_service_.handler_queue_end_->next_
-          = &task_io_service_.task_handler_;
-        task_io_service_.handler_queue_end_
-          = &task_io_service_.task_handler_;
-      }
-      else
-      {
-        task_io_service_.handler_queue_
-          = task_io_service_.handler_queue_end_
-          = &task_io_service_.task_handler_;
-      }
+      task_io_service_.handler_queue_.push(&task_io_service_.task_handler_);
     }
 
   private:
@@ -487,11 +372,11 @@
 
   // Handler object to represent the position of the task in the queue.
   class task_handler
-    : public handler_base
+    : public handler_queue::handler
   {
   public:
     task_handler()
-      : handler_base(0, 0)
+      : handler_queue::handler(0, 0)
     {
     }
   } task_handler_;
@@ -502,11 +387,8 @@
   // The count of unfinished work.
   int outstanding_work_;
 
-  // The start of a linked list of handlers that are ready to be delivered.
-  handler_base* handler_queue_;
-
-  // The end of a linked list of handlers that are ready to be delivered.
-  handler_base* handler_queue_end_;
+  // The queue of handlers that are ready to be delivered.
+  handler_queue handler_queue_;
 
   // Flag to indicate that the dispatcher has been stopped.
   bool stopped_;