
On 06/04/10 09:18, Steve Lorimer wrote:
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
(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
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
struct cb1 { typedef void (T::*type)(boost::shared_ptr<A0>); // member function of the form 'T::fn(shared_ptr<A0>)' }; //----------------------------------------------------------------------- Steve,
I'm not real sure the attached would be helpful; however, I thought maybe it would because what the attached code does is curries a functor's argument (any number) and stores them into another functor which can then be called later. I admit that doesn't sound exactly like what you want, but maybe something in the attached code would be helpful. I hope so. However, it does make use of variadic templates and some code from: https://svn.boost.org/svn/boost/sandbox/variadic_templates ; so, that might not be acceptable to you. -regards Larry