Re: [boost] boost::signal thread safety

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Timmo Stange wrote:
For a quick summary: everybody agreed on dropping the "trackable" base class design as it cannot be made thread-safe. Besides that, compatibility with the current Boost.Signals has been maintained, even though it stands in the way of optimal scalability and also complicates the implementation.
There was also the minor change to signal::combiner()/set_combiner(). I've also just dropped signals::connection::block() and unblock() from thread_safe_signals and replaced them with a signals::shared_connection_block class. A shared_connection_block object causes the connection it is created from to be blocked until the shared_connection_block is destroyed or its unblock() method is called manually. A connection will remain blocked for as long as any active shared_connection_block exists. In addition to exception safety, the shared_connection_block makes blocking useable in a multi-threaded scenario, such as two threads independently blocking the same connection for short periods, without additional locking. I'm currently reasonably satisfied with the state of thread_safe_signals. My plan now is to finish an updated version of the signals documentation that is sufficient to describe the changes that have been made, and then put the code and documentation in a tarball so it is easier for people to try out. Time and experience should clarify any remaining problem areas. The design decision that I'm most doubtful about is the explicit lock() of tracked objects in the slot class. Peter Dimov suggested an alternative of having a slot throw a bad_weak_ptr exception when called with an expired tracked object. This has the advantage of allowing one slot to be bound to another with boost::bind seamlessly, without requiring explicit setup of tracking between the slots. Unfortunately, throwing exceptions would require changes to the combiner interface. The most minimal change I can see would be requiring combiners to take into account the possibility of a slot iterator dereference throwing a bad_weak_ptr exception. This actually doesn't seem too bad. The combiner would just need to move on to the next slot if it catches an exception. - -- Frank -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux) iD8DBQFF6FMz5vihyNWuA4URAiZEAKCMItOFXrd0KyjTeyqGWcYxAzFT1gCgwbF1 OVcDU9UVAIvcVOLkOImQWks= =J3J0 -----END PGP SIGNATURE-----

Frank Mori Hess wrote:
The design decision that I'm most doubtful about is the explicit lock() of tracked objects in the slot class. Peter Dimov suggested an alternative of having a slot throw a bad_weak_ptr exception when called with an expired tracked object. This has the advantage of allowing one slot to be bound to another with boost::bind seamlessly, without requiring explicit setup of tracking between the slots. Unfortunately, throwing exceptions would require changes to the combiner interface. The most minimal change I can see would be requiring combiners to take into account the possibility of a slot iterator dereference throwing a bad_weak_ptr exception. This actually doesn't seem too bad. The combiner would just need to move on to the next slot if it catches an exception.
For clarification: the alternative tracking method we discussed simply relies on shared_ptr. A slot's connection state would depend on the reference count of the shared_ptr, which can be checked by holding a weak_ptr to the tracked object. The mentioned lock() is shared_ptr::lock() accordingly, which is used to both check and guarantee the tracked object's lifetime for the duration of a call. The fact why the combiner would need to handle bad_weak_ptr exceptions with this idea may not be so obvious either: The signal (or the slot_call_iterator) cannot simply swallow the exception, as the com- biner expects a value when dereferencing the iterator and that's not possible to guarantee when the expired slot happens to be the last callable slot of the signal (is effectively the end(), but not until the combiner tries to dereference it). For completeness I'd like to add that Peter would have preferred to drop the combiner/slot_call_iterator design, too, so that problem would not exist. I don't like this idea, because it effectively means dropping tracking altogether. The original idea is not to call a slot when a tracked object expired. This change would just put the burden on the client code and rely on exception safe slot implementations while silently swallowing the bad_weak_ptr exceptions. It's non-functionality, as the users can do something like this in any case, if they do not want to rely on Signal's tracking. Regards Timmo Stange
participants (2)
-
Frank Mori Hess
-
Timmo Stange