On Sunday 18 February 2007 12:08 am, Gottlob Frege wrote:
- do you hold any locks DURING the slot call? That's typically bad, since you have no idea what else is locked or what a slot might do, so deadlocks abound.
Well, neither implementation will deadlock, except for lock-ordering problems between external mutexes and the ones inside the signals implementation. I've got a list lock and a slot lock, and only the slot lock is held while the slot is executing. I took care that it is safe to do a blocking lock on the list lock while a slot lock is already held, and the slot lock itself is recursive so I don't see any deadlocks.
- as for the 'lock per slot' vs 'lock per signal': The solution I've come up with in the past is basically lock per slot, but more importantly *temporary* lock per slot. ie you create (or take from a pool) locks as needed, and store them in a "slot -> lock" map, so IF another thread also needs the lock for that slot, they check the map first, and obtain the same lock for that slot. Using this, if you are careful, in most cases, you don't actually end up creating the lock at all (as you have all the information necessary to see contention as it is happening, and create the locks as needed. ie you know which slot is being called, and which slot is concurrently being disconnected, and only lock if they are the same - which means don't lock on the slot call, but AFTER the call, see if another thread has come in and is waiting for you to finish. So actually it is not a lock at all, but more of an 'event' (or a 'signal' but that'd be confusing).
Not sure if that makes much sense (got a bit rambly there), but it is the seed of an idea that does work if you are careful...
That's interesting, I hadn't considered dropping the slot lock before running the slot. It would eliminate the possibility of lock-ordering problems with mutexs in the slot/client code. The slot mutex is really just to protect the disconnect and block operations, so by the time the slot is about to be run all we really need to worry about is that the slot function doesn't get deleted while it is executing. I think I could just drop the slot mutex in the slot iterator dereference operation, after either copying the slot function or using some shared_ptr magic to keep it alive, and all would be well. -- Frank