Oooh, what's perfect forwarding?
shared_ptr<event> ev = create_event<foo, bar>(obj, &foo::func, queue); // this for class foo, which has member void foo::func(bar) which we want to callback to
post_to_event<bar>(ev, data); // posts an object data of type foo to event ev
// 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_;
// 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
friend void post_to_event(boost::shared_ptr<event> &ev);
template<typename A0>
friend void post_to_event(boost::shared_ptr<event> &ev, boost::shared_ptr<A0> &data);
};
//-----------------------------------------------------------------------
// typedef generalised callback types
template<class T>
struct cb0
{
typedef void (T::*type)(); // member function of the form 'T::fn()'
};
template<class T, typename A0>
struct cb1
{
typedef void (T::*type)(boost::shared_ptr<A0>); // member function of the form 'T::fn(shared_ptr<A0>)'
};
//-----------------------------------------------------------------------
// 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<typename T>
friend boost::shared_ptr<event> create_event(boost::shared_ptr<T> that, typename cb0<T>::type cb, EventQueue &queue);
template<typename T, typename A0>
friend boost::shared_ptr<event> create_event(boost::shared_ptr<T> that, typename cb1<T, A0>::type cb, EventQueue &queue);
// event post friends
friend void post_to_event(boost::shared_ptr<event> &ev);
template<typename A0>
friend void post_to_event(boost::shared_ptr<event> &ev, boost::shared_ptr<A0> &data);
};
// helper functions which create new events
template<typename T>
boost::shared_ptr<event> create_event(boost::shared_ptr<T> that, typename cb0<T>::type cb, EventQueue &queue)
{
// encapsulate an object and it's member function using bind
return boost::shared_ptr<event>(new event(queue, boost::bind(cb, that)));
}
template<typename T, typename A0>
boost::shared_ptr<event> create_event(boost::shared_ptr<T> that, typename cb1<T, A0>::type cb, EventQueue &queue)
{
// encapsulate an object and it's member function using bind, placeholder for argument to come
return boost::shared_ptr<event>(new event(queue, boost::bind(cb, that, _1)));
}
//-----------------------------------------------------------------------
// helper functions which post events onto the event's queue
void post_to_event(boost::shared_ptr<event> &ev)
{
ev->queue_.post(ev->job_);
}
template<typename A0>
void post_to_event(boost::shared_ptr<event> &ev, boost::shared_ptr<A0> &data)
{
// bind the data to the job
ev->queue_.post(boost::bind(ev->job_, data));
}
//-----------------------------------------------------------------------
Nat Goodspeed wrote:I intended to add: if you don't mind requiring a C++1x-compliant compiler, you could use perfect forwarding instead.
boost::signals2::slot (in boost/signals2/slot.hpp) does wrap a bind() call in a way that you might adapt if this is what you want.
_______________________________________________
Boost-users mailing list
Boost-users@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users