Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_HPP
00012 #define ASIO_DETAIL_INDIRECT_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 #if defined(_MSC_VER) && (_MSC_VER >= 1310)
00025 extern "C" void _ReadWriteBarrier();
00026 # pragma intrinsic(_ReadWriteBarrier)
00027 #endif // defined(_MSC_VER) && (_MSC_VER >= 1310)
00028
00029 namespace asio {
00030 namespace detail {
00031
00032 class indirect_handler_queue
00033 : private noncopyable
00034 {
00035 public:
00036 class handler;
00037
00038
00039 class node
00040 {
00041 public:
00042 node()
00043 : version_(0),
00044 handler_(0),
00045 next_(0)
00046 {
00047 }
00048
00049 private:
00050 friend class indirect_handler_queue;
00051 unsigned long version_;
00052 handler* handler_;
00053 node* next_;
00054 };
00055
00056
00057 class handler
00058 : private noncopyable
00059 {
00060 public:
00061 void invoke()
00062 {
00063 invoke_func_(this);
00064 }
00065
00066 void destroy()
00067 {
00068 destroy_func_(this);
00069 }
00070
00071 protected:
00072 typedef void (*invoke_func_type)(handler*);
00073 typedef void (*destroy_func_type)(handler*);
00074
00075 handler(invoke_func_type invoke_func,
00076 destroy_func_type destroy_func)
00077 : node_(new node),
00078 invoke_func_(invoke_func),
00079 destroy_func_(destroy_func)
00080 {
00081 }
00082
00083 ~handler()
00084 {
00085 if (node_)
00086 delete node_;
00087 }
00088
00089 private:
00090 friend class indirect_handler_queue;
00091 node* node_;
00092 invoke_func_type invoke_func_;
00093 destroy_func_type destroy_func_;
00094 };
00095
00096
00097 class scoped_ptr
00098 : private noncopyable
00099 {
00100 public:
00101 explicit scoped_ptr(handler* h)
00102 : handler_(h)
00103 {
00104 }
00105
00106 ~scoped_ptr()
00107 {
00108 if (handler_)
00109 handler_->destroy();
00110 }
00111
00112 handler* get() const
00113 {
00114 return handler_;
00115 }
00116
00117 handler* release()
00118 {
00119 handler* tmp = handler_;
00120 handler_ = 0;
00121 return tmp;
00122 }
00123
00124 private:
00125 handler* handler_;
00126 };
00127
00128
00129 indirect_handler_queue()
00130 : front_(new node),
00131 back_(front_),
00132 next_version_(1)
00133 {
00134 }
00135
00136
00137 ~indirect_handler_queue()
00138 {
00139 while (front_)
00140 {
00141 node* tmp = front_;
00142 front_ = front_->next_;
00143 delete tmp;
00144 }
00145 }
00146
00147
00148 template <typename Handler>
00149 static handler* wrap(Handler h)
00150 {
00151
00152 typedef handler_wrapper<Handler> value_type;
00153 typedef handler_alloc_traits<Handler, value_type> alloc_traits;
00154 raw_handler_ptr<alloc_traits> raw_ptr(h);
00155 handler_ptr<alloc_traits> ptr(raw_ptr, h);
00156 return ptr.release();
00157 }
00158
00159
00160 bool poppable()
00161 {
00162 return front_->next_ != 0;
00163 }
00164
00165
00166 unsigned long front_version()
00167 {
00168 return front_->version_;
00169 }
00170
00171
00172 unsigned long back_version()
00173 {
00174 return back_->version_;
00175 }
00176
00177
00178 handler* pop()
00179 {
00180 node* n = front_;
00181 node* new_front = n->next_;
00182 if (new_front)
00183 {
00184 handler* h = new_front->handler_;
00185 h->node_ = n;
00186 new_front->handler_ = 0;
00187 front_ = new_front;
00188 return h;
00189 }
00190 return 0;
00191 }
00192
00193
00194 void push(handler* h)
00195 {
00196 node* n = h->node_;
00197 h->node_ = 0;
00198 n->version_ = next_version_;
00199 next_version_ += 2;
00200 n->handler_ = h;
00201 n->next_ = 0;
00202 memory_barrier();
00203 back_->next_ = n;
00204 back_ = n;
00205 }
00206
00207 private:
00208
00209 template <typename Handler>
00210 class handler_wrapper
00211 : public handler
00212 {
00213 public:
00214 handler_wrapper(Handler h)
00215 : handler(
00216 &handler_wrapper<Handler>::do_call,
00217 &handler_wrapper<Handler>::do_destroy),
00218 handler_(h)
00219 {
00220 }
00221
00222 static void do_call(handler* base)
00223 {
00224
00225 typedef handler_wrapper<Handler> this_type;
00226 this_type* h(static_cast<this_type*>(base));
00227 typedef handler_alloc_traits<Handler, this_type> alloc_traits;
00228 handler_ptr<alloc_traits> ptr(h->handler_, h);
00229
00230
00231
00232 Handler handler(h->handler_);
00233
00234
00235 ptr.reset();
00236
00237
00238 asio_handler_invoke_helpers::invoke(handler, &handler);
00239 }
00240
00241 static void do_destroy(handler* base)
00242 {
00243
00244 typedef handler_wrapper<Handler> this_type;
00245 this_type* h(static_cast<this_type*>(base));
00246 typedef handler_alloc_traits<Handler, this_type> alloc_traits;
00247 handler_ptr<alloc_traits> ptr(h->handler_, h);
00248
00249
00250
00251
00252
00253 Handler handler(h->handler_);
00254 (void)handler;
00255
00256
00257 ptr.reset();
00258 }
00259
00260 private:
00261 Handler handler_;
00262 };
00263
00264
00265 static void memory_barrier()
00266 {
00267 #if defined(_GLIBCXX_WRITE_MEM_BARRIER)
00268 _GLIBCXX_WRITE_MEM_BARRIER;
00269 #elif defined(_MSC_VER) && (_MSC_VER >= 1310)
00270 _ReadWriteBarrier();
00271 #else
00272 # error memory barrier required
00273 #endif
00274 }
00275
00276
00277 node* front_;
00278
00279
00280 node* back_;
00281
00282
00283 unsigned long next_version_;
00284 };
00285
00286 }
00287 }
00288
00289 #include "asio/detail/pop_options.hpp"
00290
00291 #endif // ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_HPP