Handle deletion of SignalObservers

Add a beingDeleted signal called in the SignalObserver destructor.
This commit is contained in:
Gaute Lindkvist
2020-07-01 08:50:18 +02:00
parent 30e32a1c50
commit 99762831bd

View File

@@ -44,18 +44,77 @@
namespace caf
{
class SignalObserver
class SignalEmitter;
class SignalObserver;
//==================================================================================================
/// Basic delete signal emitted by any observer when deleted.
/// Allows a regular signal to disconnect from the observer.
//==================================================================================================
class DeleteSignal
{
public:
virtual ~SignalObserver() = default;
using DisconnectCallback = std::function<void( SignalObserver* )>;
DeleteSignal( SignalObserver* observer )
: m_observer( observer )
{
}
template <typename ClassType>
void connect( ClassType* signal )
{
static_assert( std::is_convertible<ClassType*, SignalObserver*>::value,
"Only classes that inherit SignalObserver can connect as an observer of a Signal." );
DisconnectCallback lambda = [=]( SignalObserver* observer ) { ( signal->disconnect )( observer ); };
auto signalCasted = dynamic_cast<SignalObserver*>( signal );
if ( signalCasted ) m_disconnectCallbacks[signalCasted] = lambda;
}
void disconnect( SignalObserver* observer ) { m_disconnectCallbacks.erase( observer ); }
void send()
{
for ( auto signalCallbackPair : m_disconnectCallbacks )
{
signalCallbackPair.second( m_observer );
}
}
private:
std::map<SignalObserver*, DisconnectCallback> m_disconnectCallbacks;
SignalObserver* m_observer;
};
//==================================================================================================
/// SignalEmitter
/// Should be inherited by any object that emits signals.
//==================================================================================================
class SignalEmitter
{
public:
virtual ~SignalEmitter() = default;
};
//==================================================================================================
/// SignalObserver.
/// Should be inherited by any object that observes and reacts to signals.
//==================================================================================================
class SignalObserver
{
public:
DeleteSignal beingDeleted;
public:
SignalObserver()
: beingDeleted( this )
{
}
virtual ~SignalObserver() { beingDeleted.send(); }
}; // namespace caf
//==================================================================================================
/// General signal class.
/// Connect any member function with the signature void(const Signal*, const SignalData* data)
@@ -63,7 +122,7 @@ public:
/// The method should accept that data may be nullptr
//==================================================================================================
template <typename... Args>
class Signal
class Signal : public SignalObserver
{
public:
using MemberCallback = std::function<void( const SignalEmitter*, Args... args )>;
@@ -74,7 +133,13 @@ public:
: m_emitter( emitter )
{
}
virtual ~Signal() = default;
virtual ~Signal()
{
for ( auto observerCallbackPair : m_observerCallbacks )
{
observerCallbackPair.first->beingDeleted.disconnect( this );
}
}
template <typename ClassType>
void connect( ClassType* observer, void ( ClassType::*method )( const SignalEmitter*, Args... args ) )
@@ -86,9 +151,14 @@ public:
( observer->*method )( emitter, args... );
};
m_observerCallbacks[observer] = std::make_pair( lambda, true );
observer->beingDeleted.connect( this );
}
void disconnect( SignalObserver* observer ) { m_observerCallbacks.erase( observer ); }
void disconnect( SignalObserver* observer )
{
m_observerCallbacks.erase( observer );
observer->beingDeleted.disconnect( this );
}
void send( Args... args )
{
for ( auto observerCallbackPair : m_observerCallbacks )