Remove use of boost::function and std::queue in completion queue

implementation.
This commit is contained in:
chris 2003-09-28 05:00:38 +00:00
parent 19baaca214
commit 6f003905e3

View File

@ -18,8 +18,6 @@
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <queue>
#include <boost/function.hpp>
#include <boost/thread.hpp>
#include "asio/detail/pop_options.hpp"
@ -46,7 +44,8 @@ public:
task_(demuxer.get_service(service_factory<Task>())),
task_is_running_(false),
outstanding_operations_(0),
ready_completions_(),
ready_completions_(0),
ready_completions_end_(0),
interrupted_(false),
current_thread_in_pool_(),
idle_thread_count_(0),
@ -63,16 +62,16 @@ public:
while (!interrupted_ && outstanding_operations_ > 0)
{
if (!ready_completions_.empty())
if (ready_completions_)
{
completion_info& front_info = ready_completions_.front();
completion_info info;
info.handler.swap(front_info.handler);
info.context = front_info.context;
ready_completions_.pop();
completion_base* comp = ready_completions_;
ready_completions_ = comp->next_;
if (ready_completions_ == 0)
ready_completions_end_ = 0;
lock.unlock();
do_completion_upcall(info.handler);
release(*info.context);
comp->call();
release(comp->context_);
delete comp;
lock.lock();
assert(outstanding_operations_ > 0);
--outstanding_operations_;
@ -125,12 +124,10 @@ public:
++outstanding_operations_;
}
/// The type of a handler to be called when a completion is delivered.
typedef boost::function0<void> completion_handler;
// Notify the demuxer that an operation has completed.
void operation_completed(const completion_handler& handler,
completion_context& context, bool allow_nested_delivery)
template <typename Handler>
void operation_completed(Handler handler, completion_context& context,
bool allow_nested_delivery)
{
boost::mutex::scoped_lock lock(mutex_);
@ -139,7 +136,7 @@ public:
if (allow_nested_delivery && current_thread_in_pool_)
{
lock.unlock();
do_completion_upcall(handler);
completion<Handler>::do_upcall(handler);
release(context);
lock.lock();
if (--outstanding_operations_ == 0)
@ -147,26 +144,31 @@ public:
}
else
{
completion_info info;
info.handler = handler;
info.context = &context;
ready_completions_.push(info);
completion<Handler>* comp = new completion<Handler>(handler, context);
if (ready_completions_end_)
{
ready_completions_end_->next_ = comp;
ready_completions_end_ = comp;
}
else
{
ready_completions_ = ready_completions_end_ = comp;
}
if (!interrupt_one_idle_thread())
interrupt_task();
}
}
else
{
completion_info* info = new completion_info;
info->handler = handler;
info->context = &context;
acquire(context, info);
completion<Handler>* comp = new completion<Handler>(handler, context);
acquire(context, comp);
}
}
// Notify the demuxer of an operation that started and finished immediately.
void operation_immediate(const completion_handler& handler,
completion_context& context, bool allow_nested_delivery)
template <typename Handler>
void operation_immediate(Handler handler, completion_context& context,
bool allow_nested_delivery)
{
operation_started();
operation_completed(handler, context, allow_nested_delivery);
@ -178,10 +180,16 @@ public:
try
{
boost::mutex::scoped_lock lock(mutex_);
std::auto_ptr<completion_info> info(static_cast<completion_info*>(arg));
ready_completions_.push(*info);
completion_base* comp = static_cast<completion_base*>(arg);
if (ready_completions_end_)
{
ready_completions_end_->next_ = comp;
ready_completions_end_ = comp;
}
else
{
ready_completions_ = ready_completions_end_ = comp;
}
if (!interrupt_one_idle_thread())
interrupt_task();
}
@ -223,25 +231,60 @@ private:
return false;
}
// Structure containing information about a completion to be delivered.
struct completion_info
// The base class for all completions.
class completion_base
{
completion_handler handler;
completion_context* context;
public:
virtual ~completion_base()
{
}
virtual void call() = 0;
protected:
completion_base(completion_context& context)
: context_(context),
next_(0)
{
}
private:
friend class task_demuxer_service<Task>;
completion_context& context_;
completion_base* next_;
};
// Do the upcall for the given completion. This function simply prevents any
// exceptions from propagating out of the completion handler.
static void do_completion_upcall(const completion_handler& handler) throw ()
// Template for completions specific to a handler.
template <typename Handler>
class completion
: public completion_base
{
try
{
handler();
}
catch (...)
public:
completion(Handler handler, completion_context& context)
: completion_base(context),
handler_(handler)
{
}
}
virtual void call()
{
do_upcall(handler_);
}
static void do_upcall(Handler& handler)
{
try
{
handler();
}
catch (...)
{
}
}
private:
Handler handler_;
};
// Mutex to protect access to internal data.
boost::mutex mutex_;
@ -255,16 +298,16 @@ private:
// The number of operations that have not yet completed.
int outstanding_operations_;
// The type of a queue of completions.
typedef std::queue<completion_info> completion_queue;
// The start of a linked list of completions that are ready to be delivered.
completion_base* ready_completions_;
// The completions that are ready to be delivered.
completion_queue ready_completions_;
// The end of a linked list of completions that are ready to be delivered.
completion_base* ready_completions_end_;
// Flag to indicate that the dispatcher has been interrupted.
bool interrupted_;
// Thread-specific flag lag to keep track of which threads are in the pool.
// Thread-specific flag to keep track of which threads are in the pool.
tss_bool current_thread_in_pool_;
// The number of threads that are currently idle.