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
25namespace Harness {
26
27template <typename T>
28class InputIterator {
29public:
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 }
80private:
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
98template <typename T>
99class ForwardIterator {
100 T * my_ptr;
101public:
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
116template <typename T>
117class RandomIterator {
118 T * my_ptr;
119public:
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
137template <typename T>
138class ConstRandomIterator {
139 const T * my_ptr;
140public:
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