Re: Sending slots to main thread (implemented)



On Thu, 2007-08-30 at 18:07 +0200, Joaquim Duran wrote:
> En/na Joaquim Duran ha escrit:

> I've done the implementation and it works fine: I'm able to send a slot
> created at runtime to main thread.
> 
> I've attached the source code to this e-mail to check it. I think that
> implement a class like this one in glibmm will simplify the task of
> thread programming.
[snip]

Rather than specialise an asynchronous queue only for slots, it would be
better to have a templated asynchronous queue class which can contain
slots and anything else meeting the standards's copy
constructor/assignment requirements.  Most people doing threaded
programming have something like that in their locker.

This would enable users to choose their own implementation strategy -
for example, in your particular usage it may well be more efficient to
pass the variable data for the Dispatcher slot to operate on rather than
an entire slot, and in your original e-mail that was the task you set
yourself ("Yes, I know that, but,.... in the Dispatcher you are able to
connect a signal with parameters to it only once and that signal can be
emitted as many times as needed (always with the same parameters
values)").

In any event, if you do want to pass an entire slot to the queue, I
suspect it would be more efficient to have a pointer to a slot (or
shared_ptr<sigc::slot<void> >) as the contained element -
boost::shared_ptr for example has a thread-safe reference count. (I
don't know how much is involved in copying slots by value and whether
this would in fact comprise a performance advantage for this usage.)

[snip]
>  sigc::slot<void> SlotDispatcher::pop()
>  {
>   sigc::slot<void> slot;
>   Glib::Mutex::Lock lock (this->mutex);
> 
>   slot = qslot.front();
>   qslot.pop();
> 
>   return slot;
> }

You have lost strong exception safety here if the assignment operator
for sigc::slot<void>, which is called in the assignment at the call to
qslot.front() (and subject to optimisation also possibly called in the
return statement), could throw.  (Even if in fact it can't throw, if you
have a templated asynchronous queue class as suggested above this is a
definite problem).  The best course is to pass back the data as a
reference argument of the SlotDispatcher::pop() method.  This breaks
symmetry with the std::queue class interface but is inevitable with your
locking strategy if you want to maintain strong exception safety.

For this kind of usage it would also be likely to be better to use a
std::list object as the std::queue container rather than the default of
a std::deque object.

There is also a simple enhancement you can add to an asynchronouse queue
class of this kind - most generally have an additional blocking pop()
method which will wait on a condition variable until there is something
in the queue to pop off.  This can be used to implement simple thread
pools and/or work despatching schemes with dedicated worker threads.

Chris





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]