source: src/Patterns/Cacheable.hpp@ dfafe7

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
Last change on this file since dfafe7 was 986ed3, checked in by Tillmann Crueger <crueger@…>, 15 years ago

COMPILE_SPEEDUP: Replaced all implicit inclusions of iostream with forwards

  • Property mode set to 100644
File size: 6.8 KB
Line 
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>
13#include <boost/shared_ptr.hpp>
14
15#include "Helpers/Assert.hpp"
16
17#ifndef NO_CACHING
18
19 template<typename T>
20 class Cacheable : public Observer
21 {
22 // we define the states of the cacheable so we can do very fast state-checks
23 class State{
24 public:
25 State(Cacheable *_owner) :
26 busy(false),
27 owner(_owner)
28 {}
29 virtual T& getValue()=0;
30 virtual void invalidate()=0;
31 virtual bool isValid()=0;
32 virtual void enter()=0;
33 bool isBusy(){
34 return busy;
35 }
36 virtual std::string getName()=0;
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 virtual std::string getName(){
68 return "invalid";
69 }
70 };
71
72 class ValidState : public State{
73 public:
74 ValidState(Cacheable *_owner) :
75 State(_owner)
76 {}
77
78 virtual T& getValue(){
79 return content;
80 }
81
82 virtual void invalidate(){
83 State::owner->switchState(State::owner->invalidState);
84 }
85
86 virtual bool isValid(){
87 return true;
88 }
89
90 virtual void enter(){
91 State::busy= true;
92 // as soon as we enter the valid state we recalculate
93 content = State::owner->recalcMethod();
94 State::busy = false;
95 }
96
97 virtual std::string getName(){
98 return "valid";
99 }
100 private:
101 T content;
102 };
103
104 class DestroyedState : public State {
105 public:
106 DestroyedState(Cacheable *_owner) :
107 State(_owner)
108 {}
109
110 virtual T& getValue(){
111 ASSERT(0,"Cannot get a value from a Cacheable after it's Observable has died");
112 // we have to return a grossly invalid reference, because no value can be produced anymore
113 return *(static_cast<T*>(0));
114 }
115
116 virtual void invalidate(){
117 ASSERT(0,"Cannot invalidate a Cacheable after it's Observable has died");
118 }
119
120 virtual bool isValid(){
121 ASSERT(0,"Cannot check validity of a Cacheable after it's Observable has died");
122 return false;
123 }
124
125 virtual void enter(){
126 // nothing to do when entering this state
127 }
128
129 virtual std::string getName(){
130 return "destroyed";
131 }
132 };
133
134
135 typedef boost::shared_ptr<State> state_ptr;
136
137 public:
138 Cacheable(Observable *_owner, boost::function<T()> _recalcMethod, std::string name);
139 virtual ~Cacheable();
140
141 const bool isValid() const;
142 const T operator*() const;
143
144 // methods implemented for base-class Observer
145 void update(Observable *subject);
146 void subjectKilled(Observable *subject);
147 private:
148 void switchState(state_ptr newState);
149
150 mutable state_ptr state;
151 // pre-defined state so we don't have to construct to much
152 state_ptr invalidState;
153 state_ptr validState;
154 // destroyed state is not predefined, because we rarely enter that state and never leave
155
156 Observable *owner;
157 boost::function<T()> recalcMethod;
158
159 // de-activated copy constructor
160 Cacheable(const Cacheable&);
161 };
162
163
164 template<typename T>
165 Cacheable<T>::Cacheable(Observable *_owner, boost::function<T()> _recalcMethod, std::string name) :
166 Observer(name + "(Cached)"),
167 owner(_owner),
168 recalcMethod(_recalcMethod)
169 {
170 // create all states needed for this object
171 invalidState = state_ptr(new InvalidState(this));
172 validState = state_ptr(new ValidState(this));
173 state = invalidState;
174 // we sign on with the best(=lowest) priority, so cached values are recalculated before
175 // anybody else might ask for updated values
176 owner->signOn(this,-20);
177 }
178
179 // de-activated copy constructor
180 template<typename T>
181 Cacheable<T>::Cacheable(const Cacheable&){
182 ASSERT(0,"Cacheables should never be copied");
183 }
184
185 template<typename T>
186 const T Cacheable<T>::operator*() const{
187 // we can only use the cacheable when the owner is not changing at the moment
188 if(!owner->isBlocked()){
189 return state->getValue();
190 }
191 else{
192 return recalcMethod();
193 }
194 }
195
196 template<typename T>
197 Cacheable<T>::~Cacheable()
198 {
199 owner->signOff(this);
200 }
201
202 template<typename T>
203 const bool Cacheable<T>::isValid() const{
204 return state->isValid();
205 }
206
207 template<typename T>
208 void Cacheable<T>::update(Observable *subject) {
209 state->invalidate();
210 }
211
212 template<typename T>
213 void Cacheable<T>::subjectKilled(Observable *subject) {
214 state_ptr destroyed = state_ptr(new DestroyedState(this));
215 switchState(destroyed);
216 }
217
218 template<typename T>
219 void Cacheable<T>::switchState(state_ptr newState){
220 ASSERT(!state->isBusy(),"LOOP DETECTED: Cacheable state switched while recalculating.\nDid the recalculation trigger the Observable?");
221#ifdef LOG_OBSERVER
222 observerLog().addMessage() << "## Cacheable " << observerLog().getName(this) << " changed state (" << state->getName()
223 << "->" << newState->getName() << ")" << std::endl;
224#endif
225 state = newState;
226 state->enter();
227 }
228
229#else
230 template<typename T>
231 class Cacheable : public Observer
232 {
233 public:
234 Cacheable(Observable *_owner, boost::function<T()> _recalcMethod,std::string name);
235 virtual ~Cacheable();
236
237 const bool isValid() const;
238 const T operator*() const;
239
240 // methods implemented for base-class Observer
241 void update(Observable *subject);
242 void subjectKilled(Observable *subject);
243 private:
244
245 boost::function<T()> recalcMethod;
246 };
247
248 template<typename T>
249 Cacheable<T>::Cacheable(Observable *_owner, boost::function<T()> _recalcMethod, std::string name) :
250 Observer(name),
251 recalcMethod(_recalcMethod)
252 {}
253
254 template<typename T>
255 const T Cacheable<T>::operator*() const{
256 return recalcMethod();
257 }
258
259 template<typename T>
260 Cacheable<T>::~Cacheable()
261 {}
262
263 template<typename T>
264 const bool Cacheable<T>::isValid() const{
265 return true;
266 }
267
268 template<typename T>
269 void Cacheable<T>::update(Observable *subject) {
270 ASSERT(0, "Cacheable::update should never be called when caching is disabled");
271 }
272
273 template<typename T>
274 void Cacheable<T>::subjectKilled(Observable *subject){
275 ASSERT(0, "Cacheable::subjectKilled should never be called when caching is disabled");
276 }
277#endif
278
279#endif /* CACHEABLE_HPP_ */
Note: See TracBrowser for help on using the repository browser.