handler_queue.hpp
Go to the documentation of this file.
00001 //
00002 // handler_queue.hpp
00003 // ~~~~~~~~~~~~~~~~~
00004 //
00005 // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
00006 //
00007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
00008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
00009 //
00010 
00011 #ifndef ASIO_DETAIL_HANDLER_QUEUE_HPP
00012 #define ASIO_DETAIL_HANDLER_QUEUE_HPP
00013 
00014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
00015 # pragma once
00016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
00017 
00018 #include "asio/detail/push_options.hpp"
00019 
00020 #include "asio/detail/handler_alloc_helpers.hpp"
00021 #include "asio/detail/handler_invoke_helpers.hpp"
00022 #include "asio/detail/noncopyable.hpp"
00023 
00024 namespace asio {
00025 namespace detail {
00026 
00027 class handler_queue
00028   : private noncopyable
00029 {
00030 public:
00031   // Base class for handlers in the queue.
00032   class handler
00033     : private noncopyable
00034   {
00035   public:
00036     void invoke()
00037     {
00038       invoke_func_(this);
00039     }
00040 
00041     void destroy()
00042     {
00043       destroy_func_(this);
00044     }
00045 
00046   protected:
00047     typedef void (*invoke_func_type)(handler*);
00048     typedef void (*destroy_func_type)(handler*);
00049 
00050     handler(invoke_func_type invoke_func,
00051         destroy_func_type destroy_func)
00052       : next_(0),
00053         invoke_func_(invoke_func),
00054         destroy_func_(destroy_func)
00055     {
00056     }
00057 
00058     ~handler()
00059     {
00060     }
00061 
00062   private:
00063     friend class handler_queue;
00064     handler* next_;
00065     invoke_func_type invoke_func_;
00066     destroy_func_type destroy_func_;
00067   };
00068 
00069   // Smart point to manager handler lifetimes.
00070   class scoped_ptr
00071     : private noncopyable
00072   {
00073   public:
00074     explicit scoped_ptr(handler* h)
00075       : handler_(h)
00076     {
00077     }
00078 
00079     ~scoped_ptr()
00080     {
00081       if (handler_)
00082         handler_->destroy();
00083     }
00084 
00085     handler* get() const
00086     {
00087       return handler_;
00088     }
00089 
00090     handler* release()
00091     {
00092       handler* tmp = handler_;
00093       handler_ = 0;
00094       return tmp;
00095     }
00096 
00097   private:
00098     handler* handler_;
00099   };
00100 
00101   // Constructor.
00102   handler_queue()
00103     : front_(0),
00104       back_(0)
00105   {
00106   }
00107 
00108   // Wrap a handler to be pushed into the queue.
00109   template <typename Handler>
00110   static handler* wrap(Handler h)
00111   {
00112     // Allocate and construct an object to wrap the handler.
00113     typedef handler_wrapper<Handler> value_type;
00114     typedef handler_alloc_traits<Handler, value_type> alloc_traits;
00115     raw_handler_ptr<alloc_traits> raw_ptr(h);
00116     handler_ptr<alloc_traits> ptr(raw_ptr, h);
00117     return ptr.release();
00118   }
00119 
00120   // Get the handler at the front of the queue.
00121   handler* front()
00122   {
00123     return front_;
00124   }
00125 
00126   // Pop a handler from the front of the queue.
00127   void pop()
00128   {
00129     if (front_)
00130     {
00131       handler* tmp = front_;
00132       front_ = front_->next_;
00133       if (front_ == 0)
00134         back_ = 0;
00135       tmp->next_= 0;
00136     }
00137   }
00138 
00139   // Push a handler on to the back of the queue.
00140   void push(handler* h)
00141   {
00142     h->next_ = 0;
00143     if (back_)
00144     {
00145       back_->next_ = h;
00146       back_ = h;
00147     }
00148     else
00149     {
00150       front_ = back_ = h;
00151     }
00152   }
00153 
00154   // Whether the queue is empty.
00155   bool empty() const
00156   {
00157     return front_ == 0;
00158   }
00159 
00160 private:
00161   // Template wrapper for handlers.
00162   template <typename Handler>
00163   class handler_wrapper
00164     : public handler
00165   {
00166   public:
00167     handler_wrapper(Handler h)
00168       : handler(
00169           &handler_wrapper<Handler>::do_call,
00170           &handler_wrapper<Handler>::do_destroy),
00171         handler_(h)
00172     {
00173     }
00174 
00175     static void do_call(handler* base)
00176     {
00177       // Take ownership of the handler object.
00178       typedef handler_wrapper<Handler> this_type;
00179       this_type* h(static_cast<this_type*>(base));
00180       typedef handler_alloc_traits<Handler, this_type> alloc_traits;
00181       handler_ptr<alloc_traits> ptr(h->handler_, h);
00182 
00183       // Make a copy of the handler so that the memory can be deallocated before
00184       // the upcall is made.
00185       Handler handler(h->handler_);
00186 
00187       // Free the memory associated with the handler.
00188       ptr.reset();
00189 
00190       // Make the upcall.
00191       asio_handler_invoke_helpers::invoke(handler, &handler);
00192     }
00193 
00194     static void do_destroy(handler* base)
00195     {
00196       // Take ownership of the handler object.
00197       typedef handler_wrapper<Handler> this_type;
00198       this_type* h(static_cast<this_type*>(base));
00199       typedef handler_alloc_traits<Handler, this_type> alloc_traits;
00200       handler_ptr<alloc_traits> ptr(h->handler_, h);
00201 
00202       // A sub-object of the handler may be the true owner of the memory
00203       // associated with the handler. Consequently, a local copy of the handler
00204       // is required to ensure that any owning sub-object remains valid until
00205       // after we have deallocated the memory here.
00206       Handler handler(h->handler_);
00207       (void)handler;
00208 
00209       // Free the memory associated with the handler.
00210       ptr.reset();
00211     }
00212 
00213   private:
00214     Handler handler_;
00215   };
00216 
00217   // The front of the queue.
00218   handler* front_;
00219 
00220   // The back of the queue.
00221   handler* back_;
00222 };
00223 
00224 } // namespace detail
00225 } // namespace asio
00226 
00227 #include "asio/detail/pop_options.hpp"
00228 
00229 #endif // ASIO_DETAIL_HANDLER_QUEUE_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


Castor
Author(s): Carpe Noctem
autogenerated on Fri Nov 8 2013 11:05:39