|
Boost : |
From: Niall Kelly (ngktab_at_[hidden])
Date: 2002-07-16 02:20:23
Doug,
Thanks for your response on this question. The
"asynchronous" wrapper approach used as a replacement
for the default SlotFunction works fine. (Thanks also
to Peter Dimov for originally proposing the
SlotFunction parameter!).
As you described below, the operator() overloads in
the asynchronous wrapper start a worker-thread passing
it a boost::function.
My first implementation simply declared a global
thread_pool, tp, and the operator() used:
tp.add(boost::bind(f_, t1));
...
I then wanted to clean this up and allow a
boost::thread_pool reference to be somehow associated
with the asynchronous wrappers. An asynchronous
wrapper function object instance is created by the
signals implementation (and its operator() is invoked)
for each slot. I do not have access to the
asynchronous wrapper instances in my code so I can't
pass a thread_pool& to a constructor or similar....
Can you suggest an elegant mechanism by which to
associate a thread_pool with the asynchronous wrapper?
Thanks again,
Niall.
> > (3) Next Step?
> >
> > I don't fully understand how the
> slot_call_iterator
> > works. However, it is obvious that the iterators
> > passed to doJob are not valid after
> > custom_combiner::operator() has returned. Would it
> be
> > possible (within the combiner) to obtain an
> underlying
> > boost::function for each slot-call from the
> > slot_call_iterators? Perhaps this function object
> > could be passed to the worker-threads.
> >
> > Any other suggestions would be greatly
> appreciated.
> >
> > Regards,
> > Niall.
>
> The reason that the slot_call_iterators are not
> valid when the combiner
> finishes is that the arguments passed from the
> signal invocation to each
> of the slots are stored on the stack; thus, if we
> try to call the function
> object referred to by *sc_iter after the combiner
> has terminated, the
> arguments it refers to no longer exist.
>
> I would suggest that the function objects themselves
> be asynchronous, so
> that invoking a slot spawns a new thread that
> executes the target
> function. An "asynchronous" wrapper could be defined
> like this:
>
> template<typename F, typename R = typename
> F::result_type>
> struct asynchronous {
> typedef R result_type;
>
> asynchronous(F f) : f_(f) {}
>
> // for N=0..some number
> template<typename T1, typename T2, ..., typename
> TN>
> R operator()(const T1& t1, const T2& t2, ...,
> const TN& tn)
> {
> return start_a_thread(boost::bind(f, t1, t2,
> ..., tn));
> }
>
> F f_;
> };
>
> There are a few options to make all slots be
> automatically wrapped in the
> appropriate asynchronous wrapper: the first is to
> not use signal::connect
> directly, but to use a wrapper function that wraps
> "asynchronous<R>"
> around each function object before calling connect.
>
> The second option is to replace the SlotFunction
> template parameter of the
> signal class, which defaults to boost::functionN<R,
> T1, T2, ..., TN>, with
> something like asynchronous<boost::functionN<R, T1,
> T2, ..., TN> >.
> Boost.Function provides the polymorphism, but the
> asynchronous wrapper
> provides the thread start. I think this is my
> preferred method, and if it
> works to your satisfaction thank Peter Dimov for
> suggesting the
> SlotFunction parameter :)
>
> In either case, the combiner need not change.
>
> Doug
>
>
http://www.sold.com.au - SOLD.com.au
- Find yourself a bargain!
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk