Imported existing code
This commit is contained in:
293
libraries/include/boost/asio/detail/indirect_handler_queue.hpp
Normal file
293
libraries/include/boost/asio/detail/indirect_handler_queue.hpp
Normal file
@@ -0,0 +1,293 @@
|
||||
//
|
||||
// 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
|
||||
Reference in New Issue
Block a user