Event/message/notification class. More...
#include <mitkMessage.h>
Public Types | |
typedef Message | Self |
typedef MessageAbstractDelegate< A > | AbstractDelegate |
typedef std::vector < AbstractDelegate * > | ListenerList |
Public Member Functions | |
~Message () | |
void | AddListener (const AbstractDelegate &delegate) const |
void | operator+= (const AbstractDelegate &delegate) const |
void | RemoveListener (const AbstractDelegate &delegate) const |
void | operator-= (const AbstractDelegate &delegate) const |
void | Send () |
void | operator() () |
const ListenerList & | GetListeners () const |
bool | HasListeners () const |
bool | IsEmpty () const |
Protected Attributes | |
ListenerList | m_Listeners |
List of listeners. | |
itk::SimpleFastMutexLock | m_Mutex |
Event/message/notification class.
This totally ITK, Qt, VTK, whatever toolkit independent class allows one class to send out messages and another class to receive these message. This class is templated over the return type (A) of the callback functions. There are variations of this class (Message1, Message2, etc.) for sending one, two or more parameters along with the messages.
This is an implementation of the Observer pattern.
To conveniently add methods for registering/unregistering observers to Message variables of your class, you can use the mitkNewMessageMacro macros.
Here is an example how to use the macros and templates:
// An object to be send around class Law { private: std::string m_Description; public: Law(const std::string law) : m_Description(law) { } std::string GetDescription() const { return m_Description; } }; // The NewtonMachine will issue specific events class NewtonMachine { mitkNewMessageMacro(AnalysisStarted); mitkNewMessage1Macro(AnalysisStopped, bool); mitkNewMessage1Macro(LawDiscovered, const Law&); public: void StartAnalysis() { // send the "started" signal m_AnalysisStartedMessage(); // we found a new law of nature by creating one :-) Law massLaw("F=ma"); m_LawDiscoveredMessage(massLaw); } void StopAnalysis() { // send the "stop" message with false, indicating // that no error occured m_AnalysisStoppedMessage(false); } }; class Observer { private: NewtonMachine* m_Machine; public: Observer(NewtonMachine* machine) : m_Machine(machine) { // Add "observers", i.e. function pointers to the machine m_Machine->AddAnalysisStartedListener( ::mitk::MessageDelegate<Observer>(this, &Observer::MachineStarted)); m_Machine->AddAnalysisStoppedListener( ::mitk::MessageDelegate1<Observer, bool>(this, &Observer::MachineStopped)); m_Machine->AddLawDiscoveredListener( ::mitk::MessageDelegate1<Observer, const Law&>(this, &Observer::LawDiscovered)); } ~Observer() { // Always remove your observers when finished m_Machine->RemoveAnalysisStartedListener( ::mitk::MessagDelegate<Observer>(this, &Observer::MachineStarted)); m_Machine->RemoveAnalysisStoppedListener( ::mitk::MessageDelegate1<Observer, bool>(this, &Observer::MachineStopped)); m_Machine->RemoveLawDiscoveredListener( ::mitk::MessageDelegate1<Observer, const Law&>(this, &Observer::LawDiscovered)); } void MachineStarted() { std::cout << "Observed machine has started" << std::endl; } void MachineStopped(bool error) { std::cout << "Observed machine stopped " << (error ? "with an error" : "") << std::endl; } void LawDiscovered(const Law& law) { std::cout << "New law of nature discovered: " << law.GetDescription() << std::endl; } }; NewtonMachine newtonMachine; Observer observer(&newtonMachine); // This will send two events to registered observers newtonMachine.StartAnalysis(); // This will send one event to registered observers newtonMachine.StopAnalysis();
Another example of how to use these message classes can be found in the directory Testing, file mitkMessageTest.cpp
Definition at line 504 of file mitkMessage.h.
typedef MessageAbstractDelegate<A> mitk::Message< A >::AbstractDelegate |
Definition at line 509 of file mitkMessage.h.
typedef std::vector<AbstractDelegate* > mitk::Message< A >::ListenerList |
Definition at line 510 of file mitkMessage.h.
typedef Message mitk::Message< A >::Self |
Definition at line 508 of file mitkMessage.h.
mitk::Message< A >::~Message | ( | ) | [inline] |
Definition at line 512 of file mitkMessage.h.
{ for (typename ListenerList::iterator iter = m_Listeners.begin(); iter != m_Listeners.end(); ++iter ) { delete *iter; } }
void mitk::Message< A >::AddListener | ( | const AbstractDelegate & | delegate ) | const [inline] |
Definition at line 520 of file mitkMessage.h.
Referenced by mitk::Message< void >::operator+=().
{ AbstractDelegate* msgCmd = delegate.Clone(); m_Mutex.Lock(); for (typename ListenerList::iterator iter = m_Listeners.begin(); iter != m_Listeners.end(); ++iter ) { if ((*iter)->operator==(msgCmd)) { delete msgCmd; m_Mutex.Unlock(); return; } } m_Listeners.push_back(msgCmd); m_Mutex.Unlock(); }
const ListenerList& mitk::Message< A >::GetListeners | ( | ) | const [inline] |
Definition at line 591 of file mitkMessage.h.
{ return m_Listeners; }
bool mitk::Message< A >::HasListeners | ( | ) | const [inline] |
Definition at line 596 of file mitkMessage.h.
{ return !m_Listeners.empty(); }
bool mitk::Message< A >::IsEmpty | ( | ) | const [inline] |
Definition at line 601 of file mitkMessage.h.
{ return m_Listeners.empty(); }
void mitk::Message< A >::operator() | ( | ) | [inline] |
Definition at line 586 of file mitkMessage.h.
{ this->Send(); }
void mitk::Message< A >::operator+= | ( | const AbstractDelegate & | delegate ) | const [inline] |
Definition at line 539 of file mitkMessage.h.
{ this->AddListener(delegate); }
void mitk::Message< A >::operator-= | ( | const AbstractDelegate & | delegate ) | const [inline] |
Definition at line 562 of file mitkMessage.h.
{ this->RemoveListener(delegate); }
void mitk::Message< A >::RemoveListener | ( | const AbstractDelegate & | delegate ) | const [inline] |
Definition at line 544 of file mitkMessage.h.
Referenced by mitk::Message< void >::operator-=().
{ m_Mutex.Lock(); for (typename ListenerList::iterator iter = m_Listeners.begin(); iter != m_Listeners.end(); ++iter ) { if ((*iter)->operator==(&delegate)) { delete *iter; m_Listeners.erase( iter ); m_Mutex.Unlock(); return; } } m_Mutex.Unlock(); }
void mitk::Message< A >::Send | ( | ) | [inline] |
Definition at line 567 of file mitkMessage.h.
Referenced by mitk::mitkMessageTestTestClass::MessageSenderClass::DoShowFinger(), and mitk::Message< void >::operator()().
{ ListenerList listeners; { m_Mutex.Lock(); listeners.assign(m_Listeners.begin(), m_Listeners.end()); m_Mutex.Unlock(); } for (typename ListenerList::iterator iter = listeners.begin(); iter != listeners.end(); ++iter ) { // notify each listener (*iter)->Execute(); } }
ListenerList mitk::Message< A >::m_Listeners [mutable, protected] |
List of listeners.
This is declared mutable for a reason: Imagine an object that sends out notifications, e.g.
class Database { public: Message Modified; };
Now imaginge someone gets a const Database
object, because he/she should not write to the database. He/she should anyway be able to register for notifications about changes in the database -- this is why AddListener and RemoveListener are declared const
. m_Listeners must be mutable so that AddListener and RemoveListener can modify it regardless of the object's constness.
Definition at line 625 of file mitkMessage.h.
Referenced by mitk::Message< void >::AddListener(), mitk::Message< void >::GetListeners(), mitk::Message< void >::HasListeners(), mitk::Message< void >::IsEmpty(), mitk::Message< void >::RemoveListener(), mitk::Message< void >::Send(), and mitk::Message< void >::~Message().
itk::SimpleFastMutexLock mitk::Message< A >::m_Mutex [mutable, protected] |
Definition at line 626 of file mitkMessage.h.
Referenced by mitk::Message< void >::AddListener(), mitk::Message< void >::RemoveListener(), and mitk::Message< void >::Send().