Index: src/Patterns/Cacheable.hpp
===================================================================
--- src/Patterns/Cacheable.hpp	(revision c3dbe0f164703a2c4da1a1d7818c146f2b3ceb31)
+++ src/Patterns/Cacheable.hpp	(revision 052b8d0f457c092d6ce25003e75db72970ba2fb0)
@@ -11,4 +11,8 @@
 #include "Patterns/Observer.hpp"
 #include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
+#include <iostream>
+
+#include "Helpers/Assert.hpp"
 
 #ifndef NO_CACHING
@@ -17,12 +21,112 @@
   class Cacheable : public Observer
   {
+    // we define the states of the cacheable so we can do very fast state-checks
+    class State{
+    public:
+      State(Cacheable *_owner) :
+        owner(_owner),
+        busy(false)
+        {}
+      virtual T& getValue()=0;
+      virtual void invalidate()=0;
+      virtual bool isValid()=0;
+      virtual void enter()=0;
+      bool isBusy(){
+        return busy;
+      }
+    protected:
+      bool busy;
+      Cacheable *owner;
+    };
+
+    class InvalidState : public State{
+    public:
+      InvalidState(Cacheable *_owner):
+        State(_owner)
+        {}
+
+      virtual T& getValue(){
+        // set the state to valid
+        State::owner->switchState(State::owner->validState);
+        // get the value from the now valid state
+        return State::owner->state->getValue();
+      }
+
+      virtual void invalidate(){
+        // nothing to do on this message
+      }
+
+      virtual bool isValid(){
+        return false;
+      }
+
+      virtual void enter(){
+        // nothing to do when entering this
+      }
+    };
+
+    class ValidState : public State{
+    public:
+      ValidState(Cacheable *_owner) :
+        State(_owner)
+        {}
+
+      virtual T& getValue(){
+        return content;
+      }
+
+      virtual void invalidate(){
+        State::owner->switchState(State::owner->invalidState);
+      }
+
+      virtual bool isValid(){
+        return true;
+      }
+
+      virtual void enter(){
+        State::busy= true;
+        // as soon as we enter the valid state we recalculate
+        content = State::owner->recalcMethod();
+        State::busy = false;
+      }
+    private:
+      T content;
+    };
+
+    class DestroyedState : public State {
+    public:
+      DestroyedState(Cacheable *_owner) :
+        State(_owner)
+        {}
+
+      virtual T& getValue(){
+        ASSERT(0,"Cannot get a value from a Cacheable after it's Observable has died");
+        // we have to return a grossly invalid reference, because no value can be produced anymore
+        return *(static_cast<T*>(0));
+      }
+
+      virtual void invalidate(){
+        ASSERT(0,"Cannot invalidate a Cacheable after it's Observable has died");
+      }
+
+      virtual bool isValid(){
+        ASSERT(0,"Cannot check validity of a Cacheable after it's Observable has died");
+        return false;
+      }
+
+      virtual void enter(){
+        // nothing to do when entering this state
+      }
+    };
+
+
+  typedef boost::shared_ptr<State> state_ptr;
+
   public:
     Cacheable(Observable *_owner, boost::function<T()> _recalcMethod);
     virtual ~Cacheable();
 
-    const bool isValid();
-    const T& operator*();
-    const bool operator==(const T&);
-    const bool operator!=(const T&);
+    const bool isValid() const;
+    const T& operator*() const;
 
     // methods implemented for base-class Observer
@@ -30,11 +134,19 @@
     void subjectKilled(Observable *subject);
   private:
-    void checkValid();
-
-    T content;
+
+    void switchState(state_ptr newState);
+
+    mutable state_ptr state;
+    // pre-defined state so we don't have to construct to much
+    state_ptr invalidState;
+    state_ptr validState;
+    // destroyed state is not predefined, because we rarely enter that state and never leave
+
     Observable *owner;
-    bool valid;
-    bool canBeUsed;
+
     boost::function<T()> recalcMethod;
+
+    // de-activated copy constructor
+    Cacheable(const Cacheable&);
   };
 
@@ -43,8 +155,10 @@
   Cacheable<T>::Cacheable(Observable *_owner, boost::function<T()> _recalcMethod) :
     owner(_owner),
-    valid(false),
-    canBeUsed(true),
     recalcMethod(_recalcMethod)
   {
+    // create all states needed for this object
+    invalidState = state_ptr(new InvalidState(this));
+    validState = state_ptr(new ValidState(this));
+    state = invalidState;
     // we sign on with the best(=lowest) priority, so cached values are recalculated before
     // anybody else might ask for updated values
@@ -52,20 +166,13 @@
   }
 
-  template<typename T>
-  const T& Cacheable<T>::operator*(){
-    checkValid();
-    return content;
-  }
-
-  template<typename T>
-  const bool Cacheable<T>::operator==(const T& rval){
-    checkValid();
-    return (content == rval);
-  }
-
-  template<typename T>
-  const bool Cacheable<T>::operator!=(const T& rval){
-    checkValid();
-    return (content != rval);
+  // de-activated copy constructor
+  template<typename T>
+  Cacheable<T>::Cacheable(const Cacheable&){
+    ASSERT(0,"Cacheables should never be copied");
+  }
+
+  template<typename T>
+  const T& Cacheable<T>::operator*() const{
+    return state->getValue();
   }
 
@@ -77,26 +184,26 @@
 
   template<typename T>
-  const bool Cacheable<T>::isValid(){
-    return valid;
+  const bool Cacheable<T>::isValid() const{
+    return state->isValid();
   }
 
   template<typename T>
   void Cacheable<T>::update(Observable *subject) {
-    valid = false;
+    state->invalidate();
   }
 
   template<typename T>
   void Cacheable<T>::subjectKilled(Observable *subject) {
-    valid = false;
-    canBeUsed = false;
-  }
-
-  template<typename T>
-  void Cacheable<T>::checkValid(){
-    assert(canBeUsed && "Cacheable used after owner was deleted");
-    if(!isValid()){
-      content = recalcMethod();
-    }
-  }
+    state_ptr destroyed = state_ptr(new DestroyedState(this));
+    switchState(destroyed);
+  }
+
+  template<typename T>
+  void Cacheable<T>::switchState(state_ptr newState){
+    ASSERT(!state->isBusy(),"LOOP DETECTED: Cacheable state switched while recalculating.\nDid the recalculation trigger the Observable?");
+    state = newState;
+    state->enter();
+  }
+
 #else
   template<typename T>
@@ -107,8 +214,6 @@
     virtual ~Cacheable();
 
-    const bool isValid();
-    const T& operator*();
-    const bool operator==(const T&);
-    const bool operator!=(const T&);
+    const bool isValid() const;
+    const T& operator*() const;
 
     // methods implemented for base-class Observer
@@ -126,16 +231,6 @@
 
   template<typename T>
-  const T& Cacheable<T>::operator*(){
+  const T& Cacheable<T>::operator*() const{
     return recalcMethod();
-  }
-
-  template<typename T>
-  const bool Cacheable<T>::operator==(const T& rval){
-    return (recalcMethod() == rval);
-  }
-
-  template<typename T>
-  const bool Cacheable<T>::operator!=(const T& rval){
-    return (recalcMethod() != rval);
   }
 
@@ -145,5 +240,5 @@
 
   template<typename T>
-  const bool Cacheable<T>::isValid(){
+  const bool Cacheable<T>::isValid() const{
     return true;
   }
@@ -151,10 +246,10 @@
   template<typename T>
   void Cacheable<T>::update(Observable *subject) {
-    assert(0 && "Cacheable::update should never be called when caching is disabled");
-  }
-
-  template<typename T>
-  void Cacheable<T>::subjectKilled(Observable *subject) {
-    assert(0 && "Cacheable::subjectKilled should never be called when caching is disabled");
+    ASSERT(0, "Cacheable::update should never be called when caching is disabled");
+  }
+
+  template<typename T>
+  void Cacheable<T>::subjectKilled(Observable *subject){
+    ASSERT(0, "Cacheable::subjectKilled should never be called when caching is disabled");
   }
 #endif
