
Frank Mori Hess wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On Friday 23 February 2007 13:38 pm, Peter Dimov wrote:
Frank Mori Hess wrote:
Would you elaborate on the race you are thinking of? Putting track in the connection class instead of the slot class makes races possible, since the connection is established before the tracked objects are added. Admittedly, this is only a problem if you are holding the tracked objects as weak_ptrs before giving them to the signal.
This isn't very likely since you won't be able to use coord->x if you only have a weak_ptr. Typically you'll lock() and connect if that succeeds. The temporary shared_ptr will ensure that there is no race. This is easy to enforce if track() takes a shared_ptr instead of a weak_ptr.
After I've thought about it a bit more, it is worse than that. Suppose an invocation starts before you add your shared_ptr for tracking. It will lock all the tracked weak_ptrs (but not the one you haven't added yet of course) before running the slot. Then, the thread making the new connection adds its shared_ptr for tracking and moves on, its local copy going out of scope. Then, the signal invocation continues and executes the (now possibly bad) slot without ever knowing about the tracked object.
You're right, this is a problem with the second form. It can be avoided by a slight modification in the syntax: signal.track( p ).connect( bind( f, p.get() ) ); or, with some bind syntactic sugar added: signal.track( p ).connect( f, p.get() ); The slot-based formulation could look like: signal_type::slot_type( bind( f, p.get() ) ).track( p ).connect_to( signal ); or signal_type::slot_type( f, p.get() ).track( p ).connect_to( signal ); Both seem passable, the first alternative looks a bit more natural. The second has the advantage of potentially producing a reusable slot class that can operate without a signal (if we get its interface right).