Public Types | Public Member Functions | Protected Attributes

mitk::Message< A > Class Template Reference

Event/message/notification class. More...

#include <mitkMessage.h>

Inheritance diagram for mitk::Message< A >:
Inheritance graph
[legend]

List of all members.

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 ListenerListGetListeners () const
bool HasListeners () const
bool IsEmpty () const

Protected Attributes

ListenerList m_Listeners
 List of listeners.
itk::SimpleFastMutexLock m_Mutex

Detailed Description

template<typename A = void>
class mitk::Message< A >

Event/message/notification class.

See also:
mitk::BinaryThresholdTool
QmitkBinaryThresholdToolGUI

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.


Member Typedef Documentation

template<typename A = void>
typedef MessageAbstractDelegate<A> mitk::Message< A >::AbstractDelegate

Definition at line 509 of file mitkMessage.h.

template<typename A = void>
typedef std::vector<AbstractDelegate* > mitk::Message< A >::ListenerList

Definition at line 510 of file mitkMessage.h.

template<typename A = void>
typedef Message mitk::Message< A >::Self

Definition at line 508 of file mitkMessage.h.


Constructor & Destructor Documentation

template<typename A = void>
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;
      }
    }

Member Function Documentation

template<typename A = void>
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();
    }
template<typename A = void>
const ListenerList& mitk::Message< A >::GetListeners (  ) const [inline]

Definition at line 591 of file mitkMessage.h.

    {
      return m_Listeners;
    }
template<typename A = void>
bool mitk::Message< A >::HasListeners (  ) const [inline]

Definition at line 596 of file mitkMessage.h.

    {
      return !m_Listeners.empty();
    }
template<typename A = void>
bool mitk::Message< A >::IsEmpty (  ) const [inline]

Definition at line 601 of file mitkMessage.h.

    {
      return m_Listeners.empty();
    }
template<typename A = void>
void mitk::Message< A >::operator() (  ) [inline]

Definition at line 586 of file mitkMessage.h.

    {
      this->Send();
    }
template<typename A = void>
void mitk::Message< A >::operator+= ( const AbstractDelegate delegate ) const [inline]

Definition at line 539 of file mitkMessage.h.

    {
      this->AddListener(delegate);
    }
template<typename A = void>
void mitk::Message< A >::operator-= ( const AbstractDelegate delegate ) const [inline]

Definition at line 562 of file mitkMessage.h.

    {
      this->RemoveListener(delegate);
    }
template<typename A = void>
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();
    }
template<typename A = void>
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();
      }
    }

Member Data Documentation

template<typename A = void>
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().

template<typename A = void>
itk::SimpleFastMutexLock mitk::Message< A >::m_Mutex [mutable, protected]

The documentation for this class was generated from the following file:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines