Remove use of boost::function and std::queue in completion queue
implementation.
This commit is contained in:
parent
19baaca214
commit
6f003905e3
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user