123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- //
- // indirect_handler_queue.hpp
- // ~~~~~~~~~~~~~~~~~~~~~~~~~~
- //
- // Copyright (c) 2003-2008 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_INDIRECT_HANDLER_QUEUE_HPP
- #define BOOST_ASIO_DETAIL_INDIRECT_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>
- #if defined(_MSC_VER) && (_MSC_VER >= 1310)
- extern "C" void _ReadWriteBarrier();
- # pragma intrinsic(_ReadWriteBarrier)
- #endif // defined(_MSC_VER) && (_MSC_VER >= 1310)
- namespace boost {
- namespace asio {
- namespace detail {
- class indirect_handler_queue
- : private noncopyable
- {
- public:
- class handler;
- // Element for a node in the queue.
- class node
- {
- public:
- node()
- : version_(0),
- handler_(0),
- next_(0)
- {
- }
- private:
- friend class indirect_handler_queue;
- unsigned long version_;
- handler* handler_;
- node* next_;
- };
- // 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)
- : node_(new node),
- invoke_func_(invoke_func),
- destroy_func_(destroy_func)
- {
- }
- ~handler()
- {
- if (node_)
- delete node_;
- }
- private:
- friend class indirect_handler_queue;
- node* node_;
- invoke_func_type invoke_func_;
- destroy_func_type destroy_func_;
- };
- // Smart point to manager handler lifetimes.
- class scoped_ptr
- : private 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.
- indirect_handler_queue()
- : front_(new node),
- back_(front_),
- next_version_(1)
- {
- }
- // Destructor.
- ~indirect_handler_queue()
- {
- while (front_)
- {
- node* tmp = front_;
- front_ = front_->next_;
- delete tmp;
- }
- }
- // 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();
- }
- // Determine whether the queue has something ready to pop.
- bool poppable()
- {
- return front_->next_ != 0;
- }
- // The version number at the front of the queue.
- unsigned long front_version()
- {
- return front_->version_;
- }
- // The version number at the back of the queue.
- unsigned long back_version()
- {
- return back_->version_;
- }
- // Pop a handler from the front of the queue.
- handler* pop()
- {
- node* n = front_;
- node* new_front = n->next_;
- if (new_front)
- {
- handler* h = new_front->handler_;
- h->node_ = n;
- new_front->handler_ = 0;
- front_ = new_front;
- return h;
- }
- return 0;
- }
- // Push a handler on to the back of the queue.
- void push(handler* h)
- {
- node* n = h->node_;
- h->node_ = 0;
- n->version_ = next_version_;
- next_version_ += 2;
- n->handler_ = h;
- n->next_ = 0;
- memory_barrier();
- back_->next_ = n;
- back_ = n;
- }
- 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.
- boost_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);
- // A sub-object of the handler may be the true owner of the memory
- // associated with the handler. Consequently, a local copy of the handler
- // is required to ensure that any owning sub-object remains valid until
- // after we have deallocated the memory here.
- Handler handler(h->handler_);
- (void)handler;
- // Free the memory associated with the handler.
- ptr.reset();
- }
- private:
- Handler handler_;
- };
- // Helper function to create a memory barrier.
- static void memory_barrier()
- {
- #if defined(_GLIBCXX_WRITE_MEM_BARRIER)
- _GLIBCXX_WRITE_MEM_BARRIER;
- #elif defined(_MSC_VER) && (_MSC_VER >= 1310)
- _ReadWriteBarrier();
- #else
- # error memory barrier required
- #endif
- }
- // The front of the queue.
- node* front_;
- // The back of the queue.
- node* back_;
- // The next version counter to be assigned to a node.
- unsigned long next_version_;
- };
- } // namespace detail
- } // namespace asio
- } // namespace boost
- #include <boost/asio/detail/pop_options.hpp>
- #endif // BOOST_ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_HPP
|