Files
libremetaverse/libsecondlife/include/boost/asio/detail/reactor_op_queue.hpp
2006-06-08 14:47:51 +00:00

278 lines
7.2 KiB
C++

//
// reactor_op_queue.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2005 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_REACTOR_OP_QUEUE_HPP
#define BOOST_ASIO_DETAIL_REACTOR_OP_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/push_options.hpp>
#include <memory>
#include <boost/asio/detail/pop_options.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/detail/hash_map.hpp>
#include <boost/asio/detail/noncopyable.hpp>
namespace boost {
namespace asio {
namespace detail {
template <typename Descriptor>
class reactor_op_queue
: private noncopyable
{
public:
// Constructor.
reactor_op_queue()
: operations_(),
cancelled_operations_(0)
{
}
// Add a new operation to the queue. Returns true if this is the only
// operation for the given descriptor, in which case the reactor's event
// demultiplexing function call may need to be interrupted and restarted.
template <typename Handler>
bool enqueue_operation(Descriptor descriptor, Handler handler)
{
op_base* new_op = new op<Handler>(descriptor, handler);
typedef typename operation_map::iterator iterator;
typedef typename operation_map::value_type value_type;
std::pair<iterator, bool> entry =
operations_.insert(value_type(descriptor, new_op));
if (entry.second)
return true;
op_base* current_op = entry.first->second;
while (current_op->next_)
current_op = current_op->next_;
current_op->next_ = new_op;
return false;
}
// Cancel all operations associated with the descriptor. Any operations
// pending for the descriptor will be notified that they have been cancelled
// next time dispatch_cancellations is called. Returns true if any operations
// were cancelled, in which case the reactor's event demultiplexing function
// may need to be interrupted and restarted.
bool cancel_operations(Descriptor descriptor)
{
typename operation_map::iterator i = operations_.find(descriptor);
if (i != operations_.end())
{
op_base* last_op = i->second;
while (last_op->next_)
last_op = last_op->next_;
last_op->next_ = cancelled_operations_;
cancelled_operations_ = i->second;
operations_.erase(i);
return true;
}
return false;
}
// Whether there are no operations in the queue.
bool empty() const
{
return operations_.empty();
}
// Determine whether there are any operations associated with the descriptor.
bool has_operation(Descriptor descriptor) const
{
return operations_.find(descriptor) != operations_.end();
}
// Dispatch the first operation corresponding to the descriptor. Returns true
// if there are more operations queued for the descriptor.
bool dispatch_operation(Descriptor descriptor, int result)
{
typename operation_map::iterator i = operations_.find(descriptor);
if (i != operations_.end())
{
op_base* next_op = i->second->next_;
i->second->next_ = 0;
i->second->invoke(result);
if (next_op)
{
i->second = next_op;
return true;
}
else
{
operations_.erase(i);
return false;
}
}
return false;
}
// Dispatch all operations corresponding to the descriptor.
void dispatch_all_operations(Descriptor descriptor, int result)
{
typename operation_map::iterator i = operations_.find(descriptor);
if (i != operations_.end())
{
op_base* op = i->second;
operations_.erase(i);
while (op)
{
op_base* next_op = op->next_;
op->next_ = 0;
op->invoke(result);
op = next_op;
}
}
}
// Fill a descriptor set with the descriptors corresponding to each active
// operation.
template <typename Descriptor_Set>
void get_descriptors(Descriptor_Set& descriptors)
{
typename operation_map::iterator i = operations_.begin();
while (i != operations_.end())
{
descriptors.set(i->first);
++i;
}
}
// Dispatch the operations corresponding to the ready file descriptors
// contained in the given descriptor set.
template <typename Descriptor_Set>
void dispatch_descriptors(const Descriptor_Set& descriptors, int result)
{
typename operation_map::iterator i = operations_.begin();
while (i != operations_.end())
{
typename operation_map::iterator op = i++;
if (descriptors.is_set(op->first))
{
op_base* next_op = op->second->next_;
op->second->next_ = 0;
op->second->invoke(result);
if (next_op)
op->second = next_op;
else
operations_.erase(op);
}
}
}
// Dispatch any pending cancels for operations.
void dispatch_cancellations()
{
while (cancelled_operations_)
{
op_base* next_op = cancelled_operations_->next_;
cancelled_operations_->next_ = 0;
cancelled_operations_->invoke(boost::asio::error::operation_aborted);
cancelled_operations_ = next_op;
}
}
private:
// Base class for reactor operations. A function pointer is used instead of
// virtual functions to avoid the associated overhead.
class op_base
{
public:
// Get the descriptor associated with the operation.
Descriptor descriptor() const
{
return descriptor_;
}
// Perform the operation.
void invoke(int result)
{
func_(this, result);
}
protected:
typedef void (*func_type)(op_base*, int);
// Construct an operation for the given descriptor.
op_base(func_type func, Descriptor descriptor)
: func_(func),
descriptor_(descriptor),
next_(0)
{
}
// Prevent deletion through this type.
~op_base()
{
}
private:
friend class reactor_op_queue<Descriptor>;
// The function to be called to dispatch the handler.
func_type func_;
// The descriptor associated with the operation.
Descriptor descriptor_;
// The next operation for the same file descriptor.
op_base* next_;
};
// Adaptor class template for using handlers in operations.
template <typename Handler>
class op
: public op_base
{
public:
// Constructor.
op(Descriptor descriptor, Handler handler)
: op_base(&op<Handler>::invoke_handler, descriptor),
handler_(handler)
{
}
// Invoke the handler.
static void invoke_handler(op_base* base, int result)
{
std::auto_ptr<op<Handler> > o(static_cast<op<Handler>*>(base));
o->handler_(result);
}
private:
Handler handler_;
};
// The type for a map of operations.
typedef hash_map<Descriptor, op_base*> operation_map;
// The operations that are currently executing asynchronously.
operation_map operations_;
// The list of operations that have been cancelled.
op_base* cancelled_operations_;
};
} // namespace detail
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_DETAIL_REACTOR_OP_QUEUE_HPP