Ignore:
Timestamp:
Mar 25, 2010, 12:01:58 PM (16 years ago)
Author:
Tillmann Crueger <crueger@…>
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.
Message:

Merge branch 'StructureRefactoring' into MenuRefactoring

Location:
molecuilder/src/Patterns
Files:
2 added
3 edited

Legend:

Unmodified
Added
Removed
  • molecuilder/src/Patterns/Cacheable.hpp

    rdb6b872 rfe3540  
    1111#include "Patterns/Observer.hpp"
    1212#include <boost/function.hpp>
     13#include <boost/shared_ptr.hpp>
     14#include <iostream>
     15
     16#include "Helpers/Assert.hpp"
    1317
    1418#ifndef NO_CACHING
     
    1721  class Cacheable : public Observer
    1822  {
     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
    19125  public:
    20126    Cacheable(Observable *_owner, boost::function<T()> _recalcMethod);
    21127    virtual ~Cacheable();
    22128
    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;
    27131
    28132    // methods implemented for base-class Observer
     
    30134    void subjectKilled(Observable *subject);
    31135  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
    35145    Observable *owner;
    36     bool valid;
    37     bool canBeUsed;
     146
    38147    boost::function<T()> recalcMethod;
     148
     149    // de-activated copy constructor
     150    Cacheable(const Cacheable&);
    39151  };
    40152
     
    43155  Cacheable<T>::Cacheable(Observable *_owner, boost::function<T()> _recalcMethod) :
    44156    owner(_owner),
    45     valid(false),
    46     canBeUsed(true),
    47157    recalcMethod(_recalcMethod)
    48158  {
     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;
    49163    // we sign on with the best(=lowest) priority, so cached values are recalculated before
    50164    // anybody else might ask for updated values
     
    52166  }
    53167
    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    }
    70183  }
    71184
     
    77190
    78191  template<typename T>
    79   const bool Cacheable<T>::isValid(){
    80     return valid;
     192  const bool Cacheable<T>::isValid() const{
     193    return state->isValid();
    81194  }
    82195
    83196  template<typename T>
    84197  void Cacheable<T>::update(Observable *subject) {
    85     valid = false;
     198    state->invalidate();
    86199  }
    87200
    88201  template<typename T>
    89202  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
    101214#else
    102215  template<typename T>
     
    107220    virtual ~Cacheable();
    108221
    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;
    113224
    114225    // methods implemented for base-class Observer
     
    126237
    127238  template<typename T>
    128   const T& Cacheable<T>::operator*(){
     239  const T Cacheable<T>::operator*() const{
    129240    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);
    140241  }
    141242
     
    145246
    146247  template<typename T>
    147   const bool Cacheable<T>::isValid(){
     248  const bool Cacheable<T>::isValid() const{
    148249    return true;
    149250  }
     
    151252  template<typename T>
    152253  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");
    159260  }
    160261#endif
  • molecuilder/src/Patterns/Observer.cpp

    rdb6b872 rfe3540  
    1010
    1111#include <iostream>
    12 #include <cassert>
     12
     13#include "Helpers/Assert.hpp"
    1314
    1415using namespace std;
     
    127128    // observers, but still we are called by one of our sub-Observables
    128129    // 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");
    132133    return;
    133134  }
     
    148149 */
    149150void 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");
    151152  bool res = false;
    152153  callees_t *callees = 0;
     
    172173 */
    173174void 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.");
    175176  callees_t *callees = callTable[this];
    176177  callees_t::iterator iter;
     
    188189    delete callees;
    189190  }
     191}
     192
     193bool Observable::isBlocked(){
     194  return depth.count(this) > 0;
    190195}
    191196
  • molecuilder/src/Patterns/Observer.hpp

    rdb6b872 rfe3540  
    9595  virtual void signOff(Observer *target);
    9696
     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
    97103protected:
    98104  virtual void update(Observable *publisher);
     
    119125  static std::set<Observable*> busyObservables;
    120126
     127  //! @cond
    121128  // Structure for RAII-Style notification
    122129protected:
     
    133140    Observable *protege;
    134141  };
     142  //! @endcond
    135143};
    136144
Note: See TracChangeset for help on using the changeset viewer.