Cont'd work on concurrent Signal, Connection destruction
See also 7580d6aba7
This commit is contained in:
parent
031b858f47
commit
992c727959
@ -67,9 +67,7 @@ public:
|
||||
, _debug_connection (false)
|
||||
#endif
|
||||
{}
|
||||
virtual ~SignalBase () {
|
||||
Glib::Threads::Mutex::Lock lm (_destruct);
|
||||
}
|
||||
virtual ~SignalBase () { }
|
||||
virtual void disconnect (boost::shared_ptr<Connection>) = 0;
|
||||
#ifdef DEBUG_PBD_SIGNAL_CONNECTIONS
|
||||
void set_debug_connection (bool yn) { _debug_connection = yn; }
|
||||
@ -77,7 +75,6 @@ public:
|
||||
|
||||
protected:
|
||||
mutable Glib::Threads::Mutex _mutex;
|
||||
Glib::Threads::Mutex _destruct;
|
||||
std::atomic<bool> _in_dtor;
|
||||
#ifdef DEBUG_PBD_SIGNAL_CONNECTIONS
|
||||
bool _debug_connection;
|
||||
@ -98,10 +95,15 @@ public:
|
||||
|
||||
void disconnect ()
|
||||
{
|
||||
Glib::Threads::Mutex::Lock lm (_mutex);
|
||||
SignalBase* signal = _signal.exchange (0, std::memory_order_acq_rel);
|
||||
if (signal) {
|
||||
/* This will lock Signal::_mutex, or return
|
||||
* immediately if Signal is being destructed
|
||||
/* It is safe to assume that signal has not been destructed.
|
||||
* If ~Signal d'tor runs, it will call our signal_going_away()
|
||||
* which will block until we're done here.
|
||||
*
|
||||
* This will lock Signal::_mutex, and call disconnected ()
|
||||
* or return immediately if Signal is being destructed.
|
||||
*/
|
||||
signal->disconnect (shared_from_this ());
|
||||
}
|
||||
@ -117,7 +119,16 @@ public:
|
||||
void signal_going_away ()
|
||||
{
|
||||
/* called with Signal::_mutex held */
|
||||
(void*) _signal.exchange (0, std::memory_order_acq_rel);
|
||||
if (!_signal.exchange (0, std::memory_order_acq_rel)) {
|
||||
/* disconnect () grabbed the signal, but signal->disconnect()
|
||||
* has not [yet] removed the entry from the list.
|
||||
*
|
||||
* Allow disconnect () to complete, which will
|
||||
* be an effective NO-OP since SignalBase::_in_dtor is true,
|
||||
* then we can proceed.
|
||||
*/
|
||||
Glib::Threads::Mutex::Lock lm (_mutex);
|
||||
}
|
||||
if (_invalidation_record) {
|
||||
_invalidation_record->unref ();
|
||||
}
|
||||
|
@ -308,9 +308,6 @@ def signal(f, n, v):
|
||||
print("""
|
||||
\tvoid disconnect (boost::shared_ptr<Connection> c)
|
||||
\t{
|
||||
\t\t/* Prevent destruction to complete before this method returns */
|
||||
\t\tGlib::Threads::Mutex::Lock lx (_destruct);
|
||||
|
||||
\t\t/* ~ScopedConnection can call this concurrently with our d'tor */
|
||||
\t\tif (!_in_dtor.load (std::memory_order_acquire)) {
|
||||
\t\t\tGlib::Threads::Mutex::Lock lm (_mutex);
|
||||
|
Loading…
Reference in New Issue
Block a user