00001 #ifndef DVUTIL_OBSERVER_H 00002 #define DVUTIL_OBSERVER_H 00003 00004 // $Id: observer.h,v 1.2 2008/03/14 21:44:10 dvermeir Exp $ 00005 #include <set> 00006 #include <stdexcept> 00007 00008 #include <dvutil/trace.h> 00009 00010 namespace Dv { 00011 00012 00013 /** Base class for all Observable classes. */ 00014 class Observable { 00015 public: 00016 /** Base class for all Observer classes. */ 00017 class Observer { 00018 typedef std::set<Observer*> List; 00019 friend class Observable; 00020 public: 00021 virtual ~Observer() { } 00022 protected: 00023 virtual void clear_master() {} 00024 }; 00025 00026 Observable() {} 00027 00028 void remove(const Observer& observer) { 00029 observers_.erase(const_cast<Observer*>(&observer)); 00030 } 00031 00032 void add(const Observer& observer) { 00033 observers_.insert(const_cast<Observer*>(&observer)); 00034 } 00035 00036 /** Destructor. An observable may be destroyed while there are still connected observers. 00037 * Hence the call to Observer::clear_master for all connected observers. 00038 */ 00039 ~Observable() { 00040 for (Observer::List::iterator o = observers_.begin(); o!= observers_.end(); ++o) 00041 (*o)->clear_master(); 00042 } 00043 00044 const Observer::List& observers() { return observers_; } 00045 00046 private: 00047 Observer::List observers_; 00048 }; 00049 00050 template<class T> 00051 class Observer: public T::Observer { 00052 public: 00053 Observer(T* master = 0): master_(0) { set_master(master); } 00054 00055 /** @param master may be 0, in which case the current 00056 * master is removed 00057 */ 00058 T* set_master(T* master) { 00059 if (master_) 00060 master_->remove(*this); 00061 master_ = master; 00062 if (master_) 00063 master_->add(*this); 00064 return master_; 00065 } 00066 00067 ~Observer() { set_master(0); } 00068 00069 T* master() const { return master_; } 00070 private: 00071 /** Exclusively for use by Observable::~Observable */ 00072 void clear_master() { master_ = 0; } 00073 T* master_; 00074 }; 00075 } 00076 #endif 00077
dvutil-1.0.10 | [ 5 December, 2009] |