source: src/Patterns/ObservedIterator.hpp@ d1e0c0

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

Added config.h to all header files.

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