On 2/19/07, Timmo Stange
Frank Mori Hess wrote:
How about an optional callback parameter for disconnect(), which usually will be called immediately after the successful disconnection or, in the rare case of the slot being run on another thread at the time of the disconnection, after it returned (naturally from the other thread's context then)? Not specifying this parameter would imply that the caller has taken the necessary precautions to avoid all possible problems (either by externally synchronizing signal calls or by not relying on strong disconnect semantics).
The reason for this idea is simplicity of use. Keeping a close watch on resources you share between threads is everyday work, so in many cases special handling for the concurrent disconnection/invocation will not be necessary. In all other cases (when the user has no access to the called code, for example), the tools we provide should be tailored to the problem: this concurrency situation is rather unlikely and the common case should result in synchronous behavior. My connect::wait() idea would often force the user to run a separate maintenance thread for resource cleanup, in which he performs those waits - a high cost (design- and performace-wise) for something that is unlikely to happen.
This is starting to sound promising. I could also imagine that disconnect returns some kind of event that you can choose to wait on or not. Let me back up a bit: - one of the original reasons (in my head at least) for blocking on disconnect() is so that you can disconnect() in your destructor (and thus avoid having a dead object being called). I guess with weak_ptr, this is no longer a problem.(?) - If I DO want to wait, then I need to - create an 'event', (and store it somewhere - probably in my class? or in a bind passed to disconnect?) - call disconnect, passing in a callback that will set the event - wait on the event some_event_thing event(create_blocked); disconnect(bind(unblock_function, event)); e.wait(); It looks like a ALWAYS need to create the event. If we instead returned a event (possibly an empty one) be more efficient if you can tell (internally) that there is no contention? ie: signal::event e = disconnect(); e.wait(); // (may be an 'empty' event, so no real wait) ie, the signal code, instead of calling the disconnect callback, triggers the event. Not as generic as a callback, but maybe more efficient?