/* * Observer.hpp * * Created on: Jan 19, 2010 * Author: crueger */ #ifndef OBSERVER_HPP_ #define OBSERVER_HPP_ #include #include /** * Basic structure for the observer pattern * * Observers register themselves with the observables to be notified when something changes. * In the Observable code that changes attributes should be started with OBSERVE;. This macro * locks the observer mechanism while changes are done. At the end of the scope in which the * macro was placed the lock is released. When the last lock is released all changes are * propagated to the observers. * * Each observerable can have sub-observables. When one of these sub-observables changes and * notifies its observers the observable that contains them will also notify its observers. * This passing on of updates is blocked, when the main-observable is in the process of * updating many of its internal sub-observables. This means the update is not passed, if * it is produced while the main-observable itself is within any Observation block. */ class Observable; class Observer { friend class Observable; public: Observer(); virtual ~Observer(); protected: virtual void update(Observable *publisher)=0; virtual void subjectKilled(Observable *publisher)=0; }; class Observable : public Observer { public: Observable(); virtual ~Observable(); virtual void signOn(Observer *target, int priority=0); virtual void signOff(Observer *target); protected: virtual void update(Observable *publisher); virtual void subjectKilled(Observable *publisher); virtual void notifyAll(); protected: // Observer mechanism is done from a static central place /** * Internal method. * Do not call directly. Use OBSERVE macro instead */ static void start_observer_internal(Observable *publisher); /** * Internal method. * Do not call directly. Use OBSERVE macro instead */ static void finish_observer_internal(Observable *publisher); private: typedef std::multimap callees_t; static std::map depth; static std::map callTable; static std::set busyObservables; // Structure for RAII-Style notification protected: class _Observable_protector { public: _Observable_protector(Observable *); ~_Observable_protector(); private: Observable *protege; }; }; // extra macro is necessary to work with __LINE__ #define PASTE(a,b) PASTE_HELPER(a,b) #define PASTE_HELPER(a,b) a ## b #define OBSERVE Observable::_Observable_protector PASTE(_scope_obs_protector_,__LINE__)(this) // deprecated macros from before RAII was used //#define START_OBSERVER Observable::start_observer_internal(this);do{do{}while(0) //#define FINISH_OBSERVER }while(0);Observable::finish_observer_internal(this) //#define RETURN_OBSERVER( retval ) do{Observable::finish_observer_internal(this); return (retval);}while(0) #endif /* OBSERVER_HPP_ */