Changeset fe3540 for molecuilder/src/Patterns
- Timestamp:
- Mar 25, 2010, 12:01:58 PM (16 years ago)
- Children:
- eb129c
- Parents:
- db6b872 (diff), 8d9984 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- molecuilder/src/Patterns
- Files:
-
- 2 added
- 3 edited
-
Cacheable.hpp (modified) (10 diffs)
-
Observer.cpp (modified) (5 diffs)
-
Observer.hpp (modified) (3 diffs)
-
Singleton.hpp (added)
-
Singleton_impl.hpp (added)
Legend:
- Unmodified
- Added
- Removed
-
molecuilder/src/Patterns/Cacheable.hpp
rdb6b872 rfe3540 11 11 #include "Patterns/Observer.hpp" 12 12 #include <boost/function.hpp> 13 #include <boost/shared_ptr.hpp> 14 #include <iostream> 15 16 #include "Helpers/Assert.hpp" 13 17 14 18 #ifndef NO_CACHING … … 17 21 class Cacheable : public Observer 18 22 { 23 // we define the states of the cacheable so we can do very fast state-checks 24 class State{ 25 public: 26 State(Cacheable *_owner) : 27 busy(false), 28 owner(_owner) 29 {} 30 virtual T getValue()=0; 31 virtual void invalidate()=0; 32 virtual bool isValid()=0; 33 virtual void enter()=0; 34 bool isBusy(){ 35 return busy; 36 } 37 protected: 38 bool busy; 39 Cacheable *owner; 40 }; 41 42 class InvalidState : public State{ 43 public: 44 InvalidState(Cacheable *_owner): 45 State(_owner) 46 {} 47 48 virtual T getValue(){ 49 // set the state to valid 50 State::owner->switchState(State::owner->validState); 51 // get the value from the now valid state 52 return State::owner->state->getValue(); 53 } 54 55 virtual void invalidate(){ 56 // nothing to do on this message 57 } 58 59 virtual bool isValid(){ 60 return false; 61 } 62 63 virtual void enter(){ 64 // nothing to do when entering this 65 } 66 }; 67 68 class ValidState : public State{ 69 public: 70 ValidState(Cacheable *_owner) : 71 State(_owner) 72 {} 73 74 virtual T getValue(){ 75 return content; 76 } 77 78 virtual void invalidate(){ 79 State::owner->switchState(State::owner->invalidState); 80 } 81 82 virtual bool isValid(){ 83 return true; 84 } 85 86 virtual void enter(){ 87 State::busy= true; 88 // as soon as we enter the valid state we recalculate 89 content = State::owner->recalcMethod(); 90 State::busy = false; 91 } 92 private: 93 T content; 94 }; 95 96 class DestroyedState : public State { 97 public: 98 DestroyedState(Cacheable *_owner) : 99 State(_owner) 100 {} 101 102 virtual T getValue(){ 103 ASSERT(0,"Cannot get a value from a Cacheable after it's Observable has died"); 104 // we have to return a grossly invalid reference, because no value can be produced anymore 105 return *(static_cast<T*>(0)); 106 } 107 108 virtual void invalidate(){ 109 ASSERT(0,"Cannot invalidate a Cacheable after it's Observable has died"); 110 } 111 112 virtual bool isValid(){ 113 ASSERT(0,"Cannot check validity of a Cacheable after it's Observable has died"); 114 return false; 115 } 116 117 virtual void enter(){ 118 // nothing to do when entering this state 119 } 120 }; 121 122 123 typedef boost::shared_ptr<State> state_ptr; 124 19 125 public: 20 126 Cacheable(Observable *_owner, boost::function<T()> _recalcMethod); 21 127 virtual ~Cacheable(); 22 128 23 const bool isValid(); 24 const T& operator*(); 25 const bool operator==(const T&); 26 const bool operator!=(const T&); 129 const bool isValid() const; 130 const T operator*() const; 27 131 28 132 // methods implemented for base-class Observer … … 30 134 void subjectKilled(Observable *subject); 31 135 private: 32 void checkValid(); 33 34 T content; 136 137 void switchState(state_ptr newState); 138 139 mutable state_ptr state; 140 // pre-defined state so we don't have to construct to much 141 state_ptr invalidState; 142 state_ptr validState; 143 // destroyed state is not predefined, because we rarely enter that state and never leave 144 35 145 Observable *owner; 36 bool valid; 37 bool canBeUsed; 146 38 147 boost::function<T()> recalcMethod; 148 149 // de-activated copy constructor 150 Cacheable(const Cacheable&); 39 151 }; 40 152 … … 43 155 Cacheable<T>::Cacheable(Observable *_owner, boost::function<T()> _recalcMethod) : 44 156 owner(_owner), 45 valid(false),46 canBeUsed(true),47 157 recalcMethod(_recalcMethod) 48 158 { 159 // create all states needed for this object 160 invalidState = state_ptr(new InvalidState(this)); 161 validState = state_ptr(new ValidState(this)); 162 state = invalidState; 49 163 // we sign on with the best(=lowest) priority, so cached values are recalculated before 50 164 // anybody else might ask for updated values … … 52 166 } 53 167 54 template<typename T> 55 const T& Cacheable<T>::operator*(){ 56 checkValid(); 57 return content; 58 } 59 60 template<typename T> 61 const bool Cacheable<T>::operator==(const T& rval){ 62 checkValid(); 63 return (content == rval); 64 } 65 66 template<typename T> 67 const bool Cacheable<T>::operator!=(const T& rval){ 68 checkValid(); 69 return (content != rval); 168 // de-activated copy constructor 169 template<typename T> 170 Cacheable<T>::Cacheable(const Cacheable&){ 171 ASSERT(0,"Cacheables should never be copied"); 172 } 173 174 template<typename T> 175 const T Cacheable<T>::operator*() const{ 176 // we can only use the cacheable when the owner is not changing at the moment 177 if(!owner->isBlocked()){ 178 return state->getValue(); 179 } 180 else{ 181 return recalcMethod(); 182 } 70 183 } 71 184 … … 77 190 78 191 template<typename T> 79 const bool Cacheable<T>::isValid() {80 return valid;192 const bool Cacheable<T>::isValid() const{ 193 return state->isValid(); 81 194 } 82 195 83 196 template<typename T> 84 197 void Cacheable<T>::update(Observable *subject) { 85 valid = false;198 state->invalidate(); 86 199 } 87 200 88 201 template<typename T> 89 202 void Cacheable<T>::subjectKilled(Observable *subject) { 90 valid = false;91 canBeUsed = false;92 } 93 94 template<typename T> 95 void Cacheable<T>:: checkValid(){96 assert(canBeUsed && "Cacheable used after owner was deleted");97 if(!isValid()){98 content = recalcMethod();99 }100 } 203 state_ptr destroyed = state_ptr(new DestroyedState(this)); 204 switchState(destroyed); 205 } 206 207 template<typename T> 208 void Cacheable<T>::switchState(state_ptr newState){ 209 ASSERT(!state->isBusy(),"LOOP DETECTED: Cacheable state switched while recalculating.\nDid the recalculation trigger the Observable?"); 210 state = newState; 211 state->enter(); 212 } 213 101 214 #else 102 215 template<typename T> … … 107 220 virtual ~Cacheable(); 108 221 109 const bool isValid(); 110 const T& operator*(); 111 const bool operator==(const T&); 112 const bool operator!=(const T&); 222 const bool isValid() const; 223 const T operator*() const; 113 224 114 225 // methods implemented for base-class Observer … … 126 237 127 238 template<typename T> 128 const T & Cacheable<T>::operator*(){239 const T Cacheable<T>::operator*() const{ 129 240 return recalcMethod(); 130 }131 132 template<typename T>133 const bool Cacheable<T>::operator==(const T& rval){134 return (recalcMethod() == rval);135 }136 137 template<typename T>138 const bool Cacheable<T>::operator!=(const T& rval){139 return (recalcMethod() != rval);140 241 } 141 242 … … 145 246 146 247 template<typename T> 147 const bool Cacheable<T>::isValid() {248 const bool Cacheable<T>::isValid() const{ 148 249 return true; 149 250 } … … 151 252 template<typename T> 152 253 void Cacheable<T>::update(Observable *subject) { 153 assert(0 &&"Cacheable::update should never be called when caching is disabled");154 } 155 156 template<typename T> 157 void Cacheable<T>::subjectKilled(Observable *subject) {158 assert(0 &&"Cacheable::subjectKilled should never be called when caching is disabled");254 ASSERT(0, "Cacheable::update should never be called when caching is disabled"); 255 } 256 257 template<typename T> 258 void Cacheable<T>::subjectKilled(Observable *subject){ 259 ASSERT(0, "Cacheable::subjectKilled should never be called when caching is disabled"); 159 260 } 160 261 #endif -
molecuilder/src/Patterns/Observer.cpp
rdb6b872 rfe3540 10 10 11 11 #include <iostream> 12 #include <cassert> 12 13 #include "Helpers/Assert.hpp" 13 14 14 15 using namespace std; … … 127 128 // observers, but still we are called by one of our sub-Observables 128 129 // we cannot be sure observation will still work at this point 129 cerr << "Circle detected in observation-graph." << endl;130 cerr << "Observation-graph always needs to be a DAG to work correctly!" << endl;131 cerr << "Please check your observation code and fix this!" << endl;130 ASSERT(0,"Circle detected in observation-graph.\n" 131 "Observation-graph always needs to be a DAG to work correctly!\n" 132 "Please check your observation code and fix this!\n"); 132 133 return; 133 134 } … … 148 149 */ 149 150 void Observable::signOn(Observer *target,int priority) { 150 assert(priority>=-20 && priority<=+20 && "Priority out of range [-20:+20]");151 ASSERT(priority>=-20 && priority<=+20, "Priority out of range [-20:+20] when signing on Observer"); 151 152 bool res = false; 152 153 callees_t *callees = 0; … … 172 173 */ 173 174 void Observable::signOff(Observer *target) { 174 assert(callTable.count(this) &&"SignOff called for an Observable without Observers.");175 ASSERT(callTable.count(this),"SignOff called for an Observable without Observers."); 175 176 callees_t *callees = callTable[this]; 176 177 callees_t::iterator iter; … … 188 189 delete callees; 189 190 } 191 } 192 193 bool Observable::isBlocked(){ 194 return depth.count(this) > 0; 190 195 } 191 196 -
molecuilder/src/Patterns/Observer.hpp
rdb6b872 rfe3540 95 95 virtual void signOff(Observer *target); 96 96 97 /** 98 * Ask an Observer if it is currently in a blocked state, i.e. if 99 * Changes are in Progress, that are not yet published. 100 */ 101 virtual bool isBlocked(); 102 97 103 protected: 98 104 virtual void update(Observable *publisher); … … 119 125 static std::set<Observable*> busyObservables; 120 126 127 //! @cond 121 128 // Structure for RAII-Style notification 122 129 protected: … … 133 140 Observable *protege; 134 141 }; 142 //! @endcond 135 143 }; 136 144
Note:
See TracChangeset
for help on using the changeset viewer.
