On Fri, Feb 6, 2015 at 3:15 AM, Joren Heit
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