Changeset e0b6fd for src/Patterns/Cacheable.hpp
- Timestamp:
- Mar 19, 2010, 3:50:01 PM (15 years ago)
- Branches:
- Action_Thermostats, Add_AtomRandomPerturbation, Add_FitFragmentPartialChargesAction, Add_RotateAroundBondAction, Add_SelectAtomByNameAction, Added_ParseSaveFragmentResults, AddingActions_SaveParseParticleParameters, Adding_Graph_to_ChangeBondActions, Adding_MD_integration_tests, Adding_ParticleName_to_Atom, Adding_StructOpt_integration_tests, AtomFragments, Automaking_mpqc_open, AutomationFragmentation_failures, Candidate_v1.5.4, Candidate_v1.6.0, Candidate_v1.6.1, ChangeBugEmailaddress, ChangingTestPorts, ChemicalSpaceEvaluator, CombiningParticlePotentialParsing, Combining_Subpackages, Debian_Package_split, Debian_package_split_molecuildergui_only, Disabling_MemDebug, Docu_Python_wait, EmpiricalPotential_contain_HomologyGraph, EmpiricalPotential_contain_HomologyGraph_documentation, Enable_parallel_make_install, Enhance_userguide, Enhanced_StructuralOptimization, Enhanced_StructuralOptimization_continued, Example_ManyWaysToTranslateAtom, Exclude_Hydrogens_annealWithBondGraph, FitPartialCharges_GlobalError, Fix_BoundInBox_CenterInBox_MoleculeActions, Fix_ChargeSampling_PBC, Fix_ChronosMutex, Fix_FitPartialCharges, Fix_FitPotential_needs_atomicnumbers, Fix_ForceAnnealing, Fix_IndependentFragmentGrids, Fix_ParseParticles, Fix_ParseParticles_split_forward_backward_Actions, Fix_PopActions, Fix_QtFragmentList_sorted_selection, Fix_Restrictedkeyset_FragmentMolecule, Fix_StatusMsg, Fix_StepWorldTime_single_argument, Fix_Verbose_Codepatterns, Fix_fitting_potentials, Fixes, ForceAnnealing_goodresults, ForceAnnealing_oldresults, ForceAnnealing_tocheck, ForceAnnealing_with_BondGraph, ForceAnnealing_with_BondGraph_continued, ForceAnnealing_with_BondGraph_continued_betteresults, ForceAnnealing_with_BondGraph_contraction-expansion, FragmentAction_writes_AtomFragments, FragmentMolecule_checks_bonddegrees, GeometryObjects, Gui_Fixes, Gui_displays_atomic_force_velocity, ImplicitCharges, IndependentFragmentGrids, IndependentFragmentGrids_IndividualZeroInstances, IndependentFragmentGrids_IntegrationTest, IndependentFragmentGrids_Sole_NN_Calculation, JobMarket_RobustOnKillsSegFaults, JobMarket_StableWorkerPool, JobMarket_unresolvable_hostname_fix, MoreRobust_FragmentAutomation, ODR_violation_mpqc_open, PartialCharges_OrthogonalSummation, PdbParser_setsAtomName, PythonUI_with_named_parameters, QtGui_reactivate_TimeChanged_changes, Recreated_GuiChecks, Rewrite_FitPartialCharges, RotateToPrincipalAxisSystem_UndoRedo, SaturateAtoms_findBestMatching, SaturateAtoms_singleDegree, StoppableMakroAction, Subpackage_CodePatterns, Subpackage_JobMarket, Subpackage_LinearAlgebra, Subpackage_levmar, Subpackage_mpqc_open, Subpackage_vmg, Switchable_LogView, ThirdParty_MPQC_rebuilt_buildsystem, TrajectoryDependenant_MaxOrder, TremoloParser_IncreasedPrecision, TremoloParser_MultipleTimesteps, TremoloParser_setsAtomName, Ubuntu_1604_changes, stable
- Children:
- b64313
- Parents:
- ea7176
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Patterns/Cacheable.hpp
rea7176 re0b6fd 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 owner(_owner), 28 busy(false) 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); … … 28 134 void subjectKilled(Observable *subject); 29 135 private: 30 void checkValid() const; 31 32 mutable T content; 136 void switchState(state_ptr newState); 137 138 mutable state_ptr state; 139 // pre-defined state so we don't have to construct to much 140 state_ptr invalidState; 141 state_ptr validState; 142 // destroyed state is not predefined, because we rarely enter that state and never leave 143 33 144 Observable *owner; 34 mutable bool valid;35 mutable bool canBeUsed;36 145 boost::function<T()> recalcMethod; 146 147 // de-activated copy constructor 148 Cacheable(const Cacheable&); 37 149 }; 38 150 … … 41 153 Cacheable<T>::Cacheable(Observable *_owner, boost::function<T()> _recalcMethod) : 42 154 owner(_owner), 43 valid(false),44 canBeUsed(true),45 155 recalcMethod(_recalcMethod) 46 156 { 157 // create all states needed for this object 158 invalidState = state_ptr(new InvalidState(this)); 159 validState = state_ptr(new ValidState(this)); 160 state = invalidState; 47 161 // we sign on with the best(=lowest) priority, so cached values are recalculated before 48 162 // anybody else might ask for updated values … … 50 164 } 51 165 166 // de-activated copy constructor 167 template<typename T> 168 Cacheable<T>::Cacheable(const Cacheable&){ 169 ASSERT(0,"Cacheables should never be copied"); 170 } 171 52 172 template<typename T> 53 173 const T& Cacheable<T>::operator*() const{ 54 checkValid(); 55 return content; 174 return state->getValue(); 56 175 } 57 176 … … 64 183 template<typename T> 65 184 const bool Cacheable<T>::isValid() const{ 66 return valid;185 return state->isValid(); 67 186 } 68 187 69 188 template<typename T> 70 189 void Cacheable<T>::update(Observable *subject) { 71 valid = false;190 state->invalidate(); 72 191 } 73 192 74 193 template<typename T> 75 194 void Cacheable<T>::subjectKilled(Observable *subject) { 76 valid = false;77 canBeUsed = false;78 } 79 80 template<typename T> 81 void Cacheable<T>:: checkValid() const{82 assert(canBeUsed && "Cacheable used after owner was deleted");83 if(!isValid()){84 content = recalcMethod();85 86 } 195 state_ptr destroyed = state_ptr(new DestroyedState(this)); 196 switchState(destroyed); 197 } 198 199 template<typename T> 200 void Cacheable<T>::switchState(state_ptr newState){ 201 ASSERT(!state->isBusy(),"LOOP DETECTED: Cacheable state switched while recalculating.\nDid the recalculation trigger the Observable?"); 202 state = newState; 203 state->enter(); 204 } 205 87 206 #else 88 207 template<typename T> … … 125 244 template<typename T> 126 245 void Cacheable<T>::update(Observable *subject) { 127 assert(0 &&"Cacheable::update should never be called when caching is disabled");246 ASSERT(0, "Cacheable::update should never be called when caching is disabled"); 128 247 } 129 248 130 249 template<typename T> 131 250 void Cacheable<T>::subjectKilled(Observable *subject){ 132 assert(0 &&"Cacheable::subjectKilled should never be called when caching is disabled");251 ASSERT(0, "Cacheable::subjectKilled should never be called when caching is disabled"); 133 252 } 134 253 #endif
Note:
See TracChangeset
for help on using the changeset viewer.