#include <boost/enable_shared_from_this.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <stdio.h>
#include <list>
#include <iostream>
// cross-thread event queue. multiple threads can post jobs, one or many threads can execute
// jobs.
class EventQueue
{
public:
typedef boost::function<void()> Job;
private:
boost::mutex mtx_;
boost::condition cnd_;
typedef std::list<Job> Jobs;
Jobs jobs_;
int stop_;
public:
// puts a jon into the queue
void post(Job job)
{
boost::mutex::scoped_lock lock(mtx_);
jobs_.push_back(job);
cnd_.notify_one();
}
// pulls one job from the queue, returns false when stopped
bool pull(Job* job)
{
boost::mutex::scoped_lock lock(mtx_);
for(;;)
{ // handle spurious wake-ups
while(!stop_ && jobs_.empty())
cnd_.wait(lock);
if(!jobs_.empty() && 2 != stop_)
{
job->swap(jobs_.front()); // move efficiently, avoiding *job = jobs.front()
jobs_.pop_front();
return true;
}
else if(stop_)
{
return false;
}
}
}
// make pull() return false
void stop(bool cancel_jobs)
{
boost::mutex::scoped_lock lock(mtx_);
stop_ = 1 + cancel_jobs; // 1 - complete jobs, 2 - cancel jobs
cnd_.notify_all();
}
EventQueue() : stop_() {}
~EventQueue() { this->stop(true); }
};
//-----------------------------------------------------------------------
// all callbacks will be of the form void T::mem_fn(...)
// this for the callback of form T::mem_fn()
template <typename T>
class event_0
{
EventQueue &queue_; // the event queue which will process the job
boost::shared_ptr<T> that_; // the object whose mem_fun the event queue will call
typedef void (T::*CB_t)();
typedef boost::function<void()> Job;
Job job_;
public:
event_0(boost::shared_ptr<T> that, CB_t cb, EventQueue &queue) :
queue_(queue), that_(that), job_(boost::bind(cb, that))
{}
void post() { queue_.post(job_); }
};
//-----------------------------------------------------------------------