009
29.08.2006, 22:04 Uhr
(un)wissender
Niveauwart
|
Habe kronos Anmerkung mit den template-Parametern eingefügt.
C++: |
#include <boost/bind.hpp> #include <stdexcept> #include <algorithm> #include <utility>
#include <iostream>
namespace obs { namespace { template<bool init, bool exit> class BoolGuard { public: inline BoolGuard(bool & mybool); inline ~BoolGuard(); inline bool isBoolValue() const; inline void setBoolValue(bool value);
private: bool & _bool; }; template<class T, class V> class ObserverUpdater { public: inline ObserverUpdater(std::vector<T> &observerToUpdate, V const& updater); inline ~ObserverUpdater(); private: std::vector<T> & _observerToUpdate; V const& _updater; }; }
template<class T> Observable<T>::Observable() : _notify(false) { }
template<class T> Observable<T>::~Observable() { }
template<class T> void Observable<T>::registerObserver(T const& observer) { if(hasObserver(observer)) { throw std::logic_error("Observer ist already registered."); } if(_notify) { if(_observerToInsert.end() == std::find(_observerToInsert.begin(), _observerToInsert.end(), observer)) { _observerToInsert.push_back(observer); //Nur einmal merken! } //Wenn vorhanden, das wieder löschen verhindern. _observerToErase.erase( std::remove(_observerToErase.begin(), _observerToErase.end(), observer), _observerToErase.end()); } else { _observer.insert(observer); } }
template<class T> void Observable<T>::unregisterObserver(T const& observer) { if(_notify) { if(_observerToErase.end() == std::find(_observerToErase.begin(), _observerToErase.end(), observer)) { _observerToErase.push_back(observer); //Nur einmal merken! } //Wenn vorhanden, das wieder einfügen verhindern. _observerToInsert.erase( std::remove(_observerToInsert.begin(), _observerToInsert.end(), observer), _observerToInsert.end()); } else { _observer.erase(observer); } } template<class T> template<class U> void Observable<T>::notify(U u, bool allowRecursiveNotify) { if(_notify) { if(!allowRecursiveNotify) { throw std::runtime_error("runtime_error: Recursive call of notify."); } else { _recursive = true; return; } } BoolGuard<false, false> recursiveGuard(_recursive); BoolGuard<true, false> notifyGuard(_notify);
std::for_each(_observer.begin(), _observer.end(), u); typedef std::set<TestObserver *>::size_type (std::set<TestObserver *>::*Eraser) (typename std::set<TestObserver *>::key_type const&); Eraser eraser = &std::set<T>::erase; makeObserverUpdater(_observerToErase, boost::bind(eraser, &_observer, _1));
typedef std::pair<typename std::set<T>::iterator, bool> (std::set<TestObserver *>::*Inserter) (typename std::set<TestObserver *>::key_type const&); Inserter inserter = &std::set<T>::insert; makeObserverUpdater(_observerToInsert, boost::bind(inserter, &_observer, _1)); if(recursiveGuard.isBoolValue()) { notifyGuard.setBoolValue(false); if(!allowRecursiveNotify) { throw std::runtime_error("runtime_error: Recursive call of notify."); } notify(u, allowRecursiveNotify); } } template<class T> bool Observable<T>::hasObserver(T const& observer) const { bool found = _observer.end() != _observer.find(observer); if(_notify) { return (found && //vorhanden und nicht zu löschen und nicht hinzuzufügen _observerToErase.end() == std::find(_observerToErase.begin(), _observerToErase.end(), observer)) || (!found && //nicht gefunden, wird ab hinzugefügt _observerToInsert.end() != std::find(_observerToInsert.begin(), _observerToInsert.end(), observer)); } return found; }
template<class T> template<class X> void Observable<T>::makeObserverUpdater(std::vector<T> & toUpdate, X const& x) { ObserverUpdater<T, X>(toUpdate, x); }
namespace { template<bool init, bool exit> BoolGuard<init, exit>::BoolGuard(bool & mybool) : _bool(mybool) { _bool = init; }
template<bool init, bool exit> BoolGuard<init, exit>::~BoolGuard() { _bool = exit; }
template<bool init, bool exit> bool BoolGuard<init, exit>::isBoolValue() const { return _bool; }
template<bool init, bool exit> void BoolGuard<init, exit>::setBoolValue(bool value) { _bool = value; }
template<class T, class V> ObserverUpdater<T, V>::ObserverUpdater( std::vector<T> &observerToUpdate, V const& updater) : _observerToUpdate(observerToUpdate), _updater(updater) { }
template<class T, class V> ObserverUpdater<T, V>::~ObserverUpdater() { try { std::for_each(_observerToUpdate.begin(), _observerToUpdate.end(), _updater); _observerToUpdate.clear(); } catch(...) { _observerToUpdate.clear(); } } } };
|
-- Wer früher stirbt ist länger tot. |