| OLD | NEW |
| (Empty) |
| 1 // Safe sequence implementation -*- C++ -*- | |
| 2 | |
| 3 // Copyright (C) 2003, 2004, 2005, 2006, 2009 | |
| 4 // Free Software Foundation, Inc. | |
| 5 // | |
| 6 // This file is part of the GNU ISO C++ Library. This library is free | |
| 7 // software; you can redistribute it and/or modify it under the | |
| 8 // terms of the GNU General Public License as published by the | |
| 9 // Free Software Foundation; either version 3, or (at your option) | |
| 10 // any later version. | |
| 11 | |
| 12 // This library is distributed in the hope that it will be useful, | |
| 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 // GNU General Public License for more details. | |
| 16 | |
| 17 // Under Section 7 of GPL version 3, you are granted additional | |
| 18 // permissions described in the GCC Runtime Library Exception, version | |
| 19 // 3.1, as published by the Free Software Foundation. | |
| 20 | |
| 21 // You should have received a copy of the GNU General Public License and | |
| 22 // a copy of the GCC Runtime Library Exception along with this program; | |
| 23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
| 24 // <http://www.gnu.org/licenses/>. | |
| 25 | |
| 26 /** @file debug/safe_sequence.h | |
| 27 * This file is a GNU debug extension to the Standard C++ Library. | |
| 28 */ | |
| 29 | |
| 30 #ifndef _GLIBCXX_DEBUG_SAFE_SEQUENCE_H | |
| 31 #define _GLIBCXX_DEBUG_SAFE_SEQUENCE_H 1 | |
| 32 | |
| 33 #include <debug/debug.h> | |
| 34 #include <debug/macros.h> | |
| 35 #include <debug/functions.h> | |
| 36 #include <debug/safe_base.h> | |
| 37 | |
| 38 namespace __gnu_debug | |
| 39 { | |
| 40 template<typename _Iterator, typename _Sequence> | |
| 41 class _Safe_iterator; | |
| 42 | |
| 43 /** A simple function object that returns true if the passed-in | |
| 44 * value is not equal to the stored value. It saves typing over | |
| 45 * using both bind1st and not_equal. | |
| 46 */ | |
| 47 template<typename _Type> | |
| 48 class _Not_equal_to | |
| 49 { | |
| 50 _Type __value; | |
| 51 | |
| 52 public: | |
| 53 explicit _Not_equal_to(const _Type& __v) : __value(__v) { } | |
| 54 | |
| 55 bool | |
| 56 operator()(const _Type& __x) const | |
| 57 { return __value != __x; } | |
| 58 }; | |
| 59 | |
| 60 /** A function object that returns true when the given random access | |
| 61 iterator is at least @c n steps away from the given iterator. */ | |
| 62 template<typename _Iterator> | |
| 63 class _After_nth_from | |
| 64 { | |
| 65 typedef typename std::iterator_traits<_Iterator>::difference_type | |
| 66 difference_type; | |
| 67 | |
| 68 _Iterator _M_base; | |
| 69 difference_type _M_n; | |
| 70 | |
| 71 public: | |
| 72 _After_nth_from(const difference_type& __n, const _Iterator& __base) | |
| 73 : _M_base(__base), _M_n(__n) { } | |
| 74 | |
| 75 bool | |
| 76 operator()(const _Iterator& __x) const | |
| 77 { return __x - _M_base >= _M_n; } | |
| 78 }; | |
| 79 | |
| 80 /** | |
| 81 * @brief Base class for constructing a "safe" sequence type that | |
| 82 * tracks iterators that reference it. | |
| 83 * | |
| 84 * The class template %_Safe_sequence simplifies the construction of | |
| 85 * "safe" sequences that track the iterators that reference the | |
| 86 * sequence, so that the iterators are notified of changes in the | |
| 87 * sequence that may affect their operation, e.g., if the container | |
| 88 * invalidates its iterators or is destructed. This class template | |
| 89 * may only be used by deriving from it and passing the name of the | |
| 90 * derived class as its template parameter via the curiously | |
| 91 * recurring template pattern. The derived class must have @c | |
| 92 * iterator and @const_iterator types that are instantiations of | |
| 93 * class template _Safe_iterator for this sequence. Iterators will | |
| 94 * then be tracked automatically. | |
| 95 */ | |
| 96 template<typename _Sequence> | |
| 97 class _Safe_sequence : public _Safe_sequence_base | |
| 98 { | |
| 99 public: | |
| 100 /** Invalidates all iterators @c x that reference this sequence, | |
| 101 are not singular, and for which @c pred(x) returns @c | |
| 102 true. The user of this routine should be careful not to make | |
| 103 copies of the iterators passed to @p pred, as the copies may | |
| 104 interfere with the invalidation. */ | |
| 105 template<typename _Predicate> | |
| 106 void | |
| 107 _M_invalidate_if(_Predicate __pred); | |
| 108 | |
| 109 /** Transfers all iterators that reference this memory location | |
| 110 to this sequence from whatever sequence they are attached | |
| 111 to. */ | |
| 112 template<typename _Iterator> | |
| 113 void | |
| 114 _M_transfer_iter(const _Safe_iterator<_Iterator, _Sequence>& __x); | |
| 115 }; | |
| 116 | |
| 117 template<typename _Sequence> | |
| 118 template<typename _Predicate> | |
| 119 void | |
| 120 _Safe_sequence<_Sequence>:: | |
| 121 _M_invalidate_if(_Predicate __pred) | |
| 122 { | |
| 123 typedef typename _Sequence::iterator iterator; | |
| 124 typedef typename _Sequence::const_iterator const_iterator; | |
| 125 | |
| 126 __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex()); | |
| 127 for (_Safe_iterator_base* __iter = _M_iterators; __iter;) | |
| 128 { | |
| 129 iterator* __victim = static_cast<iterator*>(__iter); | |
| 130 __iter = __iter->_M_next; | |
| 131 if (!__victim->_M_singular()) | |
| 132 { | |
| 133 if (__pred(__victim->base())) | |
| 134 __victim->_M_invalidate_single(); | |
| 135 } | |
| 136 } | |
| 137 | |
| 138 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;) | |
| 139 { | |
| 140 const_iterator* __victim = static_cast<const_iterator*>(__iter2); | |
| 141 __iter2 = __iter2->_M_next; | |
| 142 if (!__victim->_M_singular()) | |
| 143 { | |
| 144 if (__pred(__victim->base())) | |
| 145 __victim->_M_invalidate_single(); | |
| 146 } | |
| 147 } | |
| 148 } | |
| 149 | |
| 150 template<typename _Sequence> | |
| 151 template<typename _Iterator> | |
| 152 void | |
| 153 _Safe_sequence<_Sequence>:: | |
| 154 _M_transfer_iter(const _Safe_iterator<_Iterator, _Sequence>& __x) | |
| 155 { | |
| 156 _Safe_sequence_base* __from = __x._M_sequence; | |
| 157 if (!__from) | |
| 158 return; | |
| 159 | |
| 160 typedef typename _Sequence::iterator iterator; | |
| 161 typedef typename _Sequence::const_iterator const_iterator; | |
| 162 | |
| 163 __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex()); | |
| 164 for (_Safe_iterator_base* __iter = __from->_M_iterators; __iter;) | |
| 165 { | |
| 166 iterator* __victim = static_cast<iterator*>(__iter); | |
| 167 __iter = __iter->_M_next; | |
| 168 if (!__victim->_M_singular() && __victim->base() == __x.base()) | |
| 169 __victim->_M_attach_single(static_cast<_Sequence*>(this)); | |
| 170 } | |
| 171 | |
| 172 for (_Safe_iterator_base* __iter2 = __from->_M_const_iterators; | |
| 173 __iter2;) | |
| 174 { | |
| 175 const_iterator* __victim = static_cast<const_iterator*>(__iter2); | |
| 176 __iter2 = __iter2->_M_next; | |
| 177 if (!__victim->_M_singular() && __victim->base() == __x.base()) | |
| 178 __victim->_M_attach_single(static_cast<_Sequence*>(this)); | |
| 179 } | |
| 180 } | |
| 181 } // namespace __gnu_debug | |
| 182 | |
| 183 #endif | |
| OLD | NEW |