Oooh, what's perfect forwarding? Anyway, back to your previous question - no, I don't *hav*e to hide the boost::bind etc, but I think my concept will wrap up a lot of functionality rather nicely, and I don't think the calling point will look too ugly. This is what I expect the creation of an event object to look like (using the code detailed below) 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 To post an event to be processed by another queue will look like this post_to_event<bar>(ev, data); // posts an object *data* of type *foo* to event *ev* So here's the code that I have come up with - doesn't compile though (of course!) - what do you think? // 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 typestemplate<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 toclass 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 eventstemplate<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 queuevoid 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)); }//----------------------------------------------------------------------- On 4 June 2010 15:05, Nat Goodspeed <nat@lindenlab.com> wrote:
Nat Goodspeed wrote:
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.
I intended to add: if you don't mind requiring a C++1x-compliant compiler, you could use perfect forwarding instead.
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users