1 | /* |
2 | Copyright (c) 2005-2019 Intel Corporation |
3 | |
4 | Licensed under the Apache License, Version 2.0 (the "License"); |
5 | you may not use this file except in compliance with the License. |
6 | You may obtain a copy of the License at |
7 | |
8 | http://www.apache.org/licenses/LICENSE-2.0 |
9 | |
10 | Unless required by applicable law or agreed to in writing, software |
11 | distributed under the License is distributed on an "AS IS" BASIS, |
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | See the License for the specific language governing permissions and |
14 | limitations under the License. |
15 | */ |
16 | |
17 | #ifndef harness_iterator_H |
18 | #define harness_iterator_H |
19 | |
20 | #include <iterator> |
21 | #include <memory> |
22 | #include "tbb/atomic.h" |
23 | #include "harness_assert.h" |
24 | |
25 | namespace Harness { |
26 | |
27 | template <typename T> |
28 | class InputIterator { |
29 | public: |
30 | typedef std::input_iterator_tag iterator_category; |
31 | typedef T value_type; |
32 | typedef typename std::allocator<T>::difference_type difference_type; |
33 | typedef typename std::allocator<T>::pointer pointer; |
34 | typedef typename std::allocator<T>::reference reference; |
35 | |
36 | explicit InputIterator ( T * ptr ) : my_ptr(ptr), my_shared_epoch(new Epoch), my_current_epoch(0) {} |
37 | |
38 | InputIterator( const InputIterator& it ) { |
39 | ASSERT(it.my_current_epoch == it.my_shared_epoch->epoch, "Copying an invalidated iterator" ); |
40 | my_ptr = it.my_ptr; |
41 | my_shared_epoch = it.my_shared_epoch; |
42 | my_current_epoch = it.my_current_epoch; |
43 | ++my_shared_epoch->refcounter; |
44 | } |
45 | |
46 | InputIterator& operator= ( const InputIterator& it ) { |
47 | ASSERT(it.my_current_epoch == it.my_shared_epoch->epoch, "Assigning an invalidated iterator" ); |
48 | my_ptr = it.my_ptr; |
49 | my_current_epoch = it.my_current_epoch; |
50 | if(my_shared_epoch == it.my_shared_epoch) |
51 | return *this; |
52 | destroy(); |
53 | my_shared_epoch = it.my_shared_epoch; |
54 | ++my_shared_epoch->refcounter; |
55 | return *this; |
56 | } |
57 | |
58 | T& operator* () const { |
59 | ASSERT(my_shared_epoch->epoch == my_current_epoch, "Dereferencing an invalidated input iterator" ); |
60 | return *my_ptr; |
61 | } |
62 | |
63 | InputIterator& operator++ () { |
64 | ASSERT(my_shared_epoch->epoch == my_current_epoch, "Incrementing an invalidated input iterator" ); |
65 | ++my_ptr; |
66 | ++my_current_epoch; |
67 | ++my_shared_epoch->epoch; |
68 | return *this; |
69 | } |
70 | |
71 | bool operator== ( const InputIterator& it ) const { |
72 | ASSERT(my_shared_epoch->epoch == my_current_epoch, "Comparing an invalidated input iterator" ); |
73 | ASSERT(it.my_shared_epoch->epoch == it.my_current_epoch, "Comparing with an invalidated input iterator" ); |
74 | return my_ptr == it.my_ptr; |
75 | } |
76 | |
77 | ~InputIterator() { |
78 | destroy(); |
79 | } |
80 | private: |
81 | void destroy() { |
82 | if(0 == --my_shared_epoch->refcounter) { |
83 | delete my_shared_epoch; |
84 | } |
85 | } |
86 | struct Epoch { |
87 | typedef tbb::atomic<size_t> Counter; |
88 | Epoch() { epoch = 0; refcounter = 1; } |
89 | Counter epoch; |
90 | Counter refcounter; |
91 | }; |
92 | |
93 | T * my_ptr; |
94 | Epoch *my_shared_epoch; |
95 | size_t my_current_epoch; |
96 | }; |
97 | |
98 | template <typename T> |
99 | class ForwardIterator { |
100 | T * my_ptr; |
101 | public: |
102 | typedef std::forward_iterator_tag iterator_category; |
103 | typedef T value_type; |
104 | typedef typename std::allocator<T>::difference_type difference_type; |
105 | typedef typename std::allocator<T>::pointer pointer; |
106 | typedef typename std::allocator<T>::reference reference; |
107 | |
108 | explicit ForwardIterator ( T * ptr ) : my_ptr(ptr){} |
109 | |
110 | ForwardIterator ( const ForwardIterator& r ) : my_ptr(r.my_ptr){} |
111 | T& operator* () const { return *my_ptr; } |
112 | ForwardIterator& operator++ () { ++my_ptr; return *this; } |
113 | bool operator== ( const ForwardIterator& r ) const { return my_ptr == r.my_ptr; } |
114 | }; |
115 | |
116 | template <typename T> |
117 | class RandomIterator { |
118 | T * my_ptr; |
119 | public: |
120 | typedef std::random_access_iterator_tag iterator_category; |
121 | typedef T value_type; |
122 | typedef typename std::allocator<T>::pointer pointer; |
123 | typedef typename std::allocator<T>::reference reference; |
124 | typedef typename std::allocator<T>::difference_type difference_type; |
125 | |
126 | explicit RandomIterator ( T * ptr ) : my_ptr(ptr){} |
127 | RandomIterator ( const RandomIterator& r ) : my_ptr(r.my_ptr){} |
128 | T& operator* () const { return *my_ptr; } |
129 | RandomIterator& operator++ () { ++my_ptr; return *this; } |
130 | bool operator== ( const RandomIterator& r ) const { return my_ptr == r.my_ptr; } |
131 | bool operator!= ( const RandomIterator& r ) const { return my_ptr != r.my_ptr; } |
132 | difference_type operator- (const RandomIterator &r) const {return my_ptr - r.my_ptr;} |
133 | RandomIterator operator+ (difference_type n) const {return RandomIterator(my_ptr + n);} |
134 | bool operator< (const RandomIterator &r) const {return my_ptr < r.my_ptr;} |
135 | }; |
136 | |
137 | template <typename T> |
138 | class ConstRandomIterator { |
139 | const T * my_ptr; |
140 | public: |
141 | typedef std::random_access_iterator_tag iterator_category; |
142 | typedef const T value_type; |
143 | typedef typename std::allocator<T>::const_pointer pointer; |
144 | typedef typename std::allocator<T>::const_reference reference; |
145 | typedef typename std::allocator<T>::difference_type difference_type; |
146 | |
147 | explicit ConstRandomIterator ( const T * ptr ) : my_ptr(ptr){} |
148 | ConstRandomIterator ( const ConstRandomIterator& r ) : my_ptr(r.my_ptr){} |
149 | const T& operator* () const { return *my_ptr; } |
150 | ConstRandomIterator& operator++ () { ++my_ptr; return *this; } |
151 | bool operator== ( const ConstRandomIterator& r ) const { return my_ptr == r.my_ptr; } |
152 | bool operator!= ( const ConstRandomIterator& r ) const { return my_ptr != r.my_ptr; } |
153 | difference_type operator- (const ConstRandomIterator &r) const {return my_ptr - r.my_ptr;} |
154 | ConstRandomIterator operator+ (difference_type n) const {return ConstRandomIterator(my_ptr + n);} |
155 | bool operator< (const ConstRandomIterator &r) const {return my_ptr < r.my_ptr;} |
156 | }; |
157 | |
158 | } // namespace Harness |
159 | |
160 | #endif //harness_iterator_H |
161 | |