/* * ObservedIterator.hpp * * Created on: Mar 4, 2010 * Author: crueger */ #ifndef OBSERVEDITERATOR_HPP_ #define OBSERVEDITERATOR_HPP_ #include "Patterns/Observer.hpp" #include // we build an iterator that observes traversion of some kind of Data structure conforming to STL template class ObservedIterator : public std::iterator::iterator_category, typename std::iterator_traits::value_type, typename std::iterator_traits::difference_type, typename std::iterator_traits::pointer, typename std::iterator_traits::reference> { public: // Some typedefs to conform to STL-Iterator structure typedef typename _Set::iterator _Iter; typedef typename _Iter::value_type value_type; typedef typename _Iter::difference_type difference_type; typedef typename _Iter::pointer pointer; typedef typename _Iter::reference reference; typedef typename _Iter::iterator_category iterator_category; ObservedIterator() : protector(0) {} ObservedIterator(_Iter iter,Observable *obs) : iter(iter), collection(obs), protector(0) {} ObservedIterator(const ObservedIterator &dest) : iter(dest.iter), collection(dest.collection), protector(dest.copyLock()) {} ~ObservedIterator(){ if(protector) delete protector; } // standard Iterator methods ObservedIterator& operator=(const ObservedIterator& dest){ if(&dest !=this){ // get the new lock first, in case the two locks point to the same observable Observable::_Observable_protector *newLock = dest.copyLock(); if(protector) delete protector; protector = newLock; // After the new lock is aquired we can safely set the iterator iter = dest.iter; // we need to know the collection, in case we still have to set the lock collection = dest.collection; } return *this; } ObservedIterator& operator++() // prefix { ++iter; return *this; } ObservedIterator operator++(int) // postfix with the dummy int parameter { ObservedIterator ret(*this); ++(*this); return ret; } ObservedIterator& operator--() // prefix { --iter; return *this; } ObservedIterator operator--(int) // postfix with the dummy int parameter { ObservedIterator ret(*this); --(*this); return ret; } bool operator==(const ObservedIterator &rhs){ return iter==rhs.iter; } bool operator!=(const ObservedIterator &rhs){ return iter!=rhs.iter; } value_type operator*(){ // access is requested... time to get the lock acquireLock(); return (*iter); } value_type *operator->(){ acquireLock(); return &(*iter); } // when we turn into a const iterator we can loose our lock operator typename _Set::const_iterator() { // typecast will be handled by the typecast method of the original iterator return iter; } private: /** * gets the lock for the collection when needed * * The lock is only acquired when the first change is done, so we can be free to do * anything with the iterator before that. I.e. step forward, turn into a const_iterator * etc. */ void acquireLock(){ if(!protector) protector = new Observable::_Observable_protector(collection); } Observable::_Observable_protector *copyLock() const{ // we only copy if we actually carry a lock if(protector){ return new Observable::_Observable_protector(*protector); } else{ return 0; } } _Iter iter; Observable *collection; Observable::_Observable_protector *protector; }; #endif /* OBSERVEDITERATOR_HPP_ */