Thanks Tony for the thorough reply. I had just made sure that signals can be (dis)connected by multiple threads in a thread-safe manner, but you are right that there is much more to it. This will be hard to implement I think, but I'll do my best!

One thing I don't quite grasp yet, is the following. Suppose one thread disconnects a slot while another fires a signal connected to that slot. You say that the implementation must make sure that the signal is not fired after the disconnect-call returns. But won't this be undefined behaviour, as there is no way of knowing which will grab the lock first?

Joren




On Fri, Feb 6, 2015 at 6:31 PM, Gottlob Frege <gottlobfrege@gmail.com> wrote:
On Fri, Feb 6, 2015 at 3:15 AM, Joren Heit <jorenheit@gmail.com> wrote:
> Ah, that's a nice one. I wonder why I haven't come across that benchmark
> myself.
>
> I haven't yet made it thread safe, but I have been wondering about this.
> Does it have to implement the slot-calls (which can itself be thread-unsafe)
> in a safe manner to be considered thread-safe? Or does it only have to be
> safe with respect to its own data?
>

For thread safety, the tricky part, but the part you want is two-fold:

1. You do not want to hold a lock _while_ the slot is being called.
In general, you never want to hold a lock while calling unknown code
(ie virtual function, pointer to function, std::function,...), because
you can't be sure whether that unknown code might grab a lock itself,
call you back (ie disconnect from within the slot, etc), or whatever,
which easily leads to hard to track deadlocks.
2. If I disconnect a slot, I don't want that slot to fire after the
disconnection.  Sounds simple, but with threads, what does "after"
really mean?  Particularly if one thread is calling disconnect while
another thread is firing the signal?  For our purposes, "after" means
that the caller, using global flags or whatever, can't tell that the
slot was called after the call to disconnect returned.

So 1 means no locks or synchronization, and 2 means you need a lock or
synchronization.

The general way to handle this is by breaking #1, but breaking it as
narrowly as possible - you still hold a lock while the slot is being
called, but it is not a lock protecting the whole list of slots, it is
a lock protecting the currently called slot only.  So you can still
add/remove slots to the signal, but if you attempt to remove the
currently running slot, it needs to remove the slot from the list, but
*if not the same thread as the slot thread* block until that slot is
finished (otherwise the slot could see itself being called after
disconnect).

And there are other complications (IIRC) like not using one mutex per
slot (wasteful), etc.

Tony
_______________________________________________
Boost-users mailing list
Boost-users@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users