//OriginalSource: // http://article.gmane.org/gmane.comp.lib.boost.user/59193 // // cross-thread event queue. multiple threads can post jobs, one or many threads can execute // jobs. #include #include #include //Above from https://svn.boost.org/svn/boost/sandbox/variadic_templates #include #include class EventQueue { public: typedef boost::function Job; private: boost::mutex mtx_; boost::condition cnd_; typedef std::list Jobs; Jobs jobs_; int stop_; // puts a job into the queue void post(Job job) { boost::mutex::scoped_lock lock(mtx_); jobs_.push_back(job); cnd_.notify_one(); } public: // 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); } // event post friends template friend void post_to_event(boost::shared_ptr &ev, boost::shared_ptr&... data); }; //----------------------------------------------------------------------- // typedef generalised callback types template struct cbn { typedef void (T::*type)(boost::shared_ptr...); // member function of the form 'T::fn(shared_ptr)' }; //----------------------------------------------------------------------- // the event class which keeps track of our job and the queue we want to post the job to class event { EventQueue &queue_; // the event queue which will process the job EventQueue::Job job_; event(EventQueue &queue, EventQueue::Job &job) : queue_(queue), job_(job) { } // event creation friends template friend boost::shared_ptr create_event (boost::shared_ptr that, typename cbn::type cb, EventQueue &queue); // event post friends template friend void post_to_event(boost::shared_ptr &ev, boost::shared_ptr&... data); }; // helper functions which create new events template struct indices_create_event ; template struct indices_create_event > { template static boost::shared_ptr _(boost::shared_ptr that, typename cbn::type cb, EventQueue &queue) { return boost::shared_ptr(new event(queue, boost::bind(cb, that, boost::arg()...))); } }; template boost::shared_ptr create_event(boost::shared_ptr that, typename cbn::type cb, EventQueue &queue) { // encapsulate an object and it's member function using bind, placeholder for argument to come typedef boost::mpl::package_range_c indices; return indices_create_event::_(that,cb,queue); } //----------------------------------------------------------------------- // helper functions which post events onto the event's queue template void post_to_event(boost::shared_ptr &ev, boost::shared_ptr&... data) { // bind the data to the job ev->queue_.post(boost::bind(ev->job_, data...)); } //-----------------------------------------------------------------------