Boost logo

Boost-Commit :

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_;


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