source: src/Patterns/Cacheable.hpp@ 2f40c0e

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 2f40c0e was f8e486, checked in by Tillmann Crueger <crueger@…>, 15 years ago

Repaired compilation with -DNO_CACHING option

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