$search
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