Get rid of caf::DeleteSignal

This commit is contained in:
Gaute Lindkvist 2020-09-16 08:39:03 +02:00
parent 3925d31795
commit d3152f5030
3 changed files with 65 additions and 66 deletions

View File

@ -119,8 +119,6 @@ void PdmObjectHandle::objectsWithReferringPtrFields( std::vector<PdmObjectHandle
//--------------------------------------------------------------------------------------------------
void PdmObjectHandle::prepareForDelete()
{
this->sendDeleteSignal();
m_parentField = nullptr;
for ( size_t i = 0; i < m_capabilities.size(); ++i )

View File

@ -40,57 +40,72 @@ using namespace caf;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
DeleteSignal::DeleteSignal( SignalObserver* observer )
: m_observer( observer )
SignalEmitter::SignalEmitter()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void DeleteSignal::disconnect( SignalObserver* observer )
SignalEmitter::~SignalEmitter()
{
// Remove the observer from the call back list
m_disconnectCallbacks.erase( observer );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void DeleteSignal::send()
std::list<AbstractSignal*> SignalEmitter::emittedSignals() const
{
// Make sure we swap out the disconnect signals to avoid
// erasing from the signal-map while looping through it.
std::map<SignalObserver*, DisconnectCallback> disconnectCallbacks;
disconnectCallbacks.swap( m_disconnectCallbacks );
for ( auto signalCallbackPair : disconnectCallbacks )
{
signalCallbackPair.second( m_observer );
}
return m_signals;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
SignalObserver::SignalObserver()
: beingDeleted( this )
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SignalObserver::sendDeleteSignal()
{
// Make sure we
beingDeleted.send();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
SignalObserver::~SignalObserver()
{
sendDeleteSignal();
disconnectAllSignals();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::list<AbstractSignal*> SignalObserver::observedSignals() const
{
return m_signals;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SignalObserver::addSignal( AbstractSignal* signalToObserve ) const
{
m_signals.push_back( signalToObserve );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SignalObserver::removeSignal( AbstractSignal* signalToRemove ) const
{
m_signals.remove( signalToRemove );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SignalObserver::disconnectAllSignals()
{
auto observedSignals = m_signals;
for ( auto observedSignal : observedSignals )
{
observedSignal->disconnect( const_cast<SignalObserver*>( this ) );
}
}

View File

@ -38,6 +38,7 @@
#include "cafAssert.h"
#include <functional>
#include <list>
#include <map>
#include <string>
#include <type_traits>
@ -47,35 +48,11 @@ namespace caf
class SignalEmitter;
class SignalObserver;
//==================================================================================================
/// Basic delete signal emitted by any observer when deleted.
/// Allows a regular signal to disconnect from the observer.
//==================================================================================================
class DeleteSignal
class AbstractSignal
{
public:
using DisconnectCallback = std::function<void( SignalObserver* )>;
DeleteSignal( SignalObserver* 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 disconnectCallback = [=]( SignalObserver* observer ) { ( signal->disconnect )( observer ); };
auto signalCasted = dynamic_cast<SignalObserver*>( signal );
if ( signalCasted ) m_disconnectCallbacks[signalCasted] = disconnectCallback;
}
void disconnect( SignalObserver* observer );
void send();
private:
std::map<SignalObserver*, DisconnectCallback> m_disconnectCallbacks;
SignalObserver* m_observer;
virtual ~AbstractSignal() = default;
virtual void disconnect( SignalObserver* observer ) = 0;
};
//==================================================================================================
@ -85,7 +62,12 @@ private:
class SignalEmitter
{
public:
virtual ~SignalEmitter() = default;
SignalEmitter();
virtual ~SignalEmitter();
std::list<AbstractSignal*> emittedSignals() const;
private:
std::list<AbstractSignal*> m_signals;
};
//==================================================================================================
@ -94,15 +76,19 @@ public:
//==================================================================================================
class SignalObserver
{
public:
DeleteSignal beingDeleted;
public:
SignalObserver();
void sendDeleteSignal();
virtual ~SignalObserver();
std::list<AbstractSignal*> observedSignals() const;
void addSignal( AbstractSignal* signalToAdd ) const;
void removeSignal( AbstractSignal* signalToRemove ) const;
}; // namespace caf
private:
void disconnectAllSignals();
private:
mutable std::list<AbstractSignal*> m_signals;
};
//==================================================================================================
/// General signal class.
@ -111,7 +97,7 @@ public:
/// The method should accept that data may be nullptr
//==================================================================================================
template <typename... Args>
class Signal : public SignalObserver
class Signal : public AbstractSignal
{
public:
using MemberCallback = std::function<void( const SignalEmitter*, Args... args )>;
@ -146,7 +132,7 @@ public:
{
for ( auto observerCallbackPair : m_observerCallbacks )
{
observerCallbackPair.first->beingDeleted.disconnect( this );
observerCallbackPair.first->removeSignal( this );
}
}
@ -166,16 +152,16 @@ public:
static_assert( std::is_convertible<ClassType*, SignalObserver*>::value,
"Only classes that inherit SignalObserver can connect as an observer of a Signal." );
m_observerCallbacks[observer] = std::make_pair( callback, true );
observer->beingDeleted.connect( this );
observer->addSignal( this );
}
// Disconnect an observer from the signal. Do this only when the relationship between the
// observer and emitter is severed but the object kept alive.
// There's no need to do this when deleting the observer.
void disconnect( SignalObserver* observer )
void disconnect( SignalObserver* observer ) override
{
m_observerCallbacks.erase( observer );
observer->beingDeleted.disconnect( this );
observer->removeSignal( this );
}
void send( Args... args )