source: src/Patterns/ObservedIterator.hpp@ a80f419

Last change on this file since a80f419 was a80f419, checked in by Frederik Heber <heber@…>, 15 years ago

First version.

Everything was extracted from project MoleCuilder and adapted such that it
runs on its own (i.e. new configure.ac, Makefile.am structure, stuff for
libtool versioning, ...)

  • Property mode set to 100644
File size: 3.8 KB
Line 
1/*
2 * ObservedIterator.hpp
3 *
4 * Created on: Mar 4, 2010
5 * Author: crueger
6 */
7
8#ifndef OBSERVEDITERATOR_HPP_
9#define OBSERVEDITERATOR_HPP_
10
11#include "Patterns/Observer.hpp"
12
13#include <iterator>
14
15// we build an iterator that observes traversion of some kind of Data structure conforming to STL
16template<class _Set>
17class ObservedIterator
18 : public std::iterator<typename std::iterator_traits<typename _Set::iterator>::iterator_category,
19 typename std::iterator_traits<typename _Set::iterator>::value_type,
20 typename std::iterator_traits<typename _Set::iterator>::difference_type,
21 typename std::iterator_traits<typename _Set::iterator>::pointer,
22 typename std::iterator_traits<typename _Set::iterator>::reference>
23{
24public:
25 // Some typedefs to conform to STL-Iterator structure
26 typedef typename _Set::iterator _Iter;
27 typedef typename _Iter::value_type value_type;
28 typedef typename _Iter::difference_type difference_type;
29 typedef typename _Iter::pointer pointer;
30 typedef typename _Iter::reference reference;
31 typedef typename _Iter::iterator_category iterator_category;
32
33 ObservedIterator() :
34 protector(0)
35 {}
36
37 ObservedIterator(_Iter iter,Observable *obs) :
38 iter(iter),
39 collection(obs),
40 protector(0)
41 {}
42
43 ObservedIterator(const ObservedIterator &dest) :
44 iter(dest.iter),
45 collection(dest.collection),
46 protector(dest.copyLock())
47 {}
48
49 ~ObservedIterator(){
50 if(protector)
51 delete protector;
52 }
53
54 // standard Iterator methods
55 ObservedIterator& operator=(const ObservedIterator& dest){
56 if(&dest !=this){
57 // get the new lock first, in case the two locks point to the same observable
58 Observable::_Observable_protector *newLock = dest.copyLock();
59 if(protector)
60 delete protector;
61 protector = newLock;
62 // After the new lock is aquired we can safely set the iterator
63 iter = dest.iter;
64 // we need to know the collection, in case we still have to set the lock
65 collection = dest.collection;
66 }
67 return *this;
68 }
69
70 ObservedIterator& operator++() // prefix
71 {
72 ++iter;
73 return *this;
74 }
75
76 ObservedIterator operator++(int) // postfix with the dummy int parameter
77 {
78 ObservedIterator ret(*this);
79 ++(*this);
80 return ret;
81 }
82
83 ObservedIterator& operator--() // prefix
84 {
85 --iter;
86 return *this;
87 }
88
89 ObservedIterator operator--(int) // postfix with the dummy int parameter
90 {
91 ObservedIterator ret(*this);
92 --(*this);
93 return ret;
94 }
95
96 bool operator==(const ObservedIterator &rhs){
97 return iter==rhs.iter;
98 }
99
100 bool operator!=(const ObservedIterator &rhs){
101 return iter!=rhs.iter;
102 }
103
104 value_type operator*(){
105 // access is requested... time to get the lock
106 acquireLock();
107 return (*iter);
108 }
109
110 value_type *operator->(){
111 acquireLock();
112 return &(*iter);
113 }
114
115 // when we turn into a const iterator we can loose our lock
116 operator typename _Set::const_iterator() {
117 // typecast will be handled by the typecast method of the original iterator
118 return iter;
119 }
120
121private:
122
123 /**
124 * gets the lock for the collection when needed
125 *
126 * The lock is only acquired when the first change is done, so we can be free to do
127 * anything with the iterator before that. I.e. step forward, turn into a const_iterator
128 * etc.
129 */
130 void acquireLock(){
131 if(!protector)
132 protector = new Observable::_Observable_protector(collection);
133 }
134
135 Observable::_Observable_protector *copyLock() const{
136 // we only copy if we actually carry a lock
137 if(protector){
138 return new Observable::_Observable_protector(*protector);
139 }
140 else{
141 return 0;
142 }
143 }
144
145 _Iter iter;
146 Observable *collection;
147 Observable::_Observable_protector *protector;
148};
149
150#endif /* OBSERVEDITERATOR_HPP_ */
Note: See TracBrowser for help on using the repository browser.