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 |