Boost logo

Boost :

From: Niall Kelly (ngktab_at_[hidden])
Date: 2002-07-10 23:06:00


Hi,

I am working on a project in which we would like to be
able to run the slots that are connected to a signal
in a thread pool. (I am using Boost 1.28.0, the most
recent Boost.Signals from the CVS repository and David
Moore's thread pool implementation from Boost Files on
Yahoo).

We thought that using a custom Combiner for the signal
would be a useful place from which to pass the "slot
work" on to the thread pool. Essentially, the combiner
passes the slot_call_iterator to the thread pool as
follows:

void
custom_combiner::operator()(InputIterator first,
                            InputIterator last) const
{
  while (first != last)
  {
    tp.add(job_adapter(doJob, first));
    first++;
  }
  
  // tp.join() - see below for discussion
}

...

typedef
boost::signal<void,double>::slot_call_iterator
sc_iter;

void doJob(sc_iter iter)
{
  *iter;
}

...

The job_adapter used by the combiner is similar to
that in David Moore's thread-pool example usage but
with int replaced by sc_iter.

(1) Why join _was_ used

With the call to join above uncommented, the test
program "succeeds" i.e. each of the connected slots
runs in a thread allocated by the thread pool. (The
slots used for this test simply sleep for varying
amounts of time (related to the double argument in the
signal signature) and display the times at which they
start and finish).

The reason we needed the join in order to "succeed" is
that without it, the combiner's operator() returns
before the various doJob threads have used the sc_iter
parameter. As soon as custom_combiner::operator()
returns, these iterators are invalid (presumably the
container of slots over which they iterate no longer
exists). With join uncommented, the combiner only
returns after the doJob threads have completed.

(2) Why the use of join is not a real solution

The problem, of course is that we do not want to have
to join (the thread pool is no longer usable AND the
fact that we join means that the signal invocation
effectively blocks until each slot (running in a
thread-pool thread) completes).

The original concept was that by running the slots in
a thread-pool, the signal invocation would just kick
off the worker-threads to do the "slot work" and
immediately return.

(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.

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