mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 23:05:04 +01:00
Cont'd work on concurrent Signal, Connection destruction
See also 7580d6aba7
This commit is contained in:
parent
031b858f47
commit
992c727959
2 changed files with 18 additions and 10 deletions
|
|
@ -67,9 +67,7 @@ public:
|
||||||
, _debug_connection (false)
|
, _debug_connection (false)
|
||||||
#endif
|
#endif
|
||||||
{}
|
{}
|
||||||
virtual ~SignalBase () {
|
virtual ~SignalBase () { }
|
||||||
Glib::Threads::Mutex::Lock lm (_destruct);
|
|
||||||
}
|
|
||||||
virtual void disconnect (boost::shared_ptr<Connection>) = 0;
|
virtual void disconnect (boost::shared_ptr<Connection>) = 0;
|
||||||
#ifdef DEBUG_PBD_SIGNAL_CONNECTIONS
|
#ifdef DEBUG_PBD_SIGNAL_CONNECTIONS
|
||||||
void set_debug_connection (bool yn) { _debug_connection = yn; }
|
void set_debug_connection (bool yn) { _debug_connection = yn; }
|
||||||
|
|
@ -77,7 +75,6 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
mutable Glib::Threads::Mutex _mutex;
|
mutable Glib::Threads::Mutex _mutex;
|
||||||
Glib::Threads::Mutex _destruct;
|
|
||||||
std::atomic<bool> _in_dtor;
|
std::atomic<bool> _in_dtor;
|
||||||
#ifdef DEBUG_PBD_SIGNAL_CONNECTIONS
|
#ifdef DEBUG_PBD_SIGNAL_CONNECTIONS
|
||||||
bool _debug_connection;
|
bool _debug_connection;
|
||||||
|
|
@ -98,10 +95,15 @@ public:
|
||||||
|
|
||||||
void disconnect ()
|
void disconnect ()
|
||||||
{
|
{
|
||||||
|
Glib::Threads::Mutex::Lock lm (_mutex);
|
||||||
SignalBase* signal = _signal.exchange (0, std::memory_order_acq_rel);
|
SignalBase* signal = _signal.exchange (0, std::memory_order_acq_rel);
|
||||||
if (signal) {
|
if (signal) {
|
||||||
/* This will lock Signal::_mutex, or return
|
/* It is safe to assume that signal has not been destructed.
|
||||||
* immediately if Signal is being 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 ());
|
signal->disconnect (shared_from_this ());
|
||||||
}
|
}
|
||||||
|
|
@ -117,7 +119,16 @@ public:
|
||||||
void signal_going_away ()
|
void signal_going_away ()
|
||||||
{
|
{
|
||||||
/* called with Signal::_mutex held */
|
/* 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) {
|
if (_invalidation_record) {
|
||||||
_invalidation_record->unref ();
|
_invalidation_record->unref ();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -308,9 +308,6 @@ def signal(f, n, v):
|
||||||
print("""
|
print("""
|
||||||
\tvoid disconnect (boost::shared_ptr<Connection> c)
|
\tvoid disconnect (boost::shared_ptr<Connection> c)
|
||||||
\t{
|
\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\t/* ~ScopedConnection can call this concurrently with our d'tor */
|
||||||
\t\tif (!_in_dtor.load (std::memory_order_acquire)) {
|
\t\tif (!_in_dtor.load (std::memory_order_acquire)) {
|
||||||
\t\t\tGlib::Threads::Mutex::Lock lm (_mutex);
|
\t\t\tGlib::Threads::Mutex::Lock lm (_mutex);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue