source: src/Patterns/Cacheable.hpp@ b64313

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 Candidate_v1.7.0 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
Last change on this file since b64313 was e0b6fd, checked in by Tillmann Crueger <crueger@…>, 16 years ago

Rebuilt Cacheables using the state pattern

  • Property mode set to 100644
File size: 6.1 KB
RevLine 
[e3c8b4]1/*
2 * Cacheable.hpp
3 *
4 * Created on: Feb 2, 2010
5 * Author: crueger
6 */
7
8#ifndef CACHEABLE_HPP_
9#define CACHEABLE_HPP_
10
11#include "Patterns/Observer.hpp"
12#include <boost/function.hpp>
[e0b6fd]13#include <boost/shared_ptr.hpp>
14#include <iostream>
15
16#include "Helpers/Assert.hpp"
[e3c8b4]17
[9ad391]18#ifndef NO_CACHING
19
20 template<typename T>
21 class Cacheable : public Observer
22 {
[e0b6fd]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
[9ad391]125 public:
126 Cacheable(Observable *_owner, boost::function<T()> _recalcMethod);
127 virtual ~Cacheable();
128
[ea7176]129 const bool isValid() const;
130 const T& operator*() const;
[9ad391]131
132 // methods implemented for base-class Observer
133 void update(Observable *subject);
134 void subjectKilled(Observable *subject);
135 private:
[e0b6fd]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
[9ad391]143
144 Observable *owner;
145 boost::function<T()> recalcMethod;
[e0b6fd]146
147 // de-activated copy constructor
148 Cacheable(const Cacheable&);
[9ad391]149 };
150
151
152 template<typename T>
153 Cacheable<T>::Cacheable(Observable *_owner, boost::function<T()> _recalcMethod) :
154 owner(_owner),
[24a5e0]155 recalcMethod(_recalcMethod)
[9ad391]156 {
[e0b6fd]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;
[314ff6]161 // we sign on with the best(=lowest) priority, so cached values are recalculated before
162 // anybody else might ask for updated values
163 owner->signOn(this,-20);
[e3c8b4]164 }
[9ad391]165
[e0b6fd]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
[9ad391]172 template<typename T>
[ea7176]173 const T& Cacheable<T>::operator*() const{
[e0b6fd]174 return state->getValue();
[9ad391]175 }
176
177 template<typename T>
178 Cacheable<T>::~Cacheable()
179 {
180 owner->signOff(this);
181 }
182
183 template<typename T>
[ea7176]184 const bool Cacheable<T>::isValid() const{
[e0b6fd]185 return state->isValid();
[9ad391]186 }
187
188 template<typename T>
189 void Cacheable<T>::update(Observable *subject) {
[e0b6fd]190 state->invalidate();
[9ad391]191 }
192
193 template<typename T>
194 void Cacheable<T>::subjectKilled(Observable *subject) {
[e0b6fd]195 state_ptr destroyed = state_ptr(new DestroyedState(this));
196 switchState(destroyed);
[9ad391]197 }
198
199 template<typename T>
[e0b6fd]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();
[9ad391]204 }
[e0b6fd]205
[9ad391]206#else
207 template<typename T>
208 class Cacheable : public Observer
209 {
210 public:
211 Cacheable(Observable *_owner, boost::function<T()> _recalcMethod);
212 virtual ~Cacheable();
213
[ea7176]214 const bool isValid() const;
215 const T& operator*() const;
[9ad391]216
217 // methods implemented for base-class Observer
218 void update(Observable *subject);
219 void subjectKilled(Observable *subject);
220 private:
221
222 boost::function<T()> recalcMethod;
223 };
224
225 template<typename T>
226 Cacheable<T>::Cacheable(Observable *_owner, boost::function<T()> _recalcMethod) :
227 recalcMethod(_recalcMethod)
228 {}
229
230 template<typename T>
[ea7176]231 const T& Cacheable<T>::operator*() const{
[9ad391]232 return recalcMethod();
233 }
234
235 template<typename T>
236 Cacheable<T>::~Cacheable()
237 {}
238
239 template<typename T>
[ea7176]240 const bool Cacheable<T>::isValid() const{
[9ad391]241 return true;
242 }
243
244 template<typename T>
245 void Cacheable<T>::update(Observable *subject) {
[e0b6fd]246 ASSERT(0, "Cacheable::update should never be called when caching is disabled");
[9ad391]247 }
248
249 template<typename T>
[ea7176]250 void Cacheable<T>::subjectKilled(Observable *subject){
[e0b6fd]251 ASSERT(0, "Cacheable::subjectKilled should never be called when caching is disabled");
[9ad391]252 }
253#endif
[e3c8b4]254
255#endif /* CACHEABLE_HPP_ */
Note: See TracBrowser for help on using the repository browser.