| 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 | |