/* * 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 wrapped in * START_OBSERVER ... END_OBSERVER blocks. If other methods are called that also contain * Observation blocks from there, these functions wont trigger notifications. Only the end * of the final observation block triggers the update of Observers. * * Returning from observed code should be done using the RETURN_OBSERVER() macro. This way the Observer mechanism * is notified that the method is left. * * 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 START_OBSERVER macro instead */ static void start_observer_internal(Observable *publisher); /** * Internal method. * Do not call directly. Use FINISH_OBSERVER 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; }; #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_ */