|
Boost Users : |
Subject: Re: [Boost-users] [bind] & [function] How do I store member functions with generalised arguments for later invocation?
From: Larry Evans (cppljevans_at_[hidden])
Date: 2010-06-04 14:06:55
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<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 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>)'
> };
> //-----------------------------------------------------------------------
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
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net