libstdc++
safe_base.h
Go to the documentation of this file.
1
// Safe sequence/iterator base implementation -*- C++ -*-
2
3
// Copyright (C) 2003, 2004, 2005, 2006, 2009, 2010
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_base.h
27
* This file is a GNU debug extension to the Standard C++ Library.
28
*/
29
30
#ifndef _GLIBCXX_DEBUG_SAFE_BASE_H
31
#define _GLIBCXX_DEBUG_SAFE_BASE_H 1
32
33
#include <
ext/concurrence.h
>
34
35
namespace
__gnu_debug
36
{
37
class
_Safe_sequence_base;
38
39
/** \brief Basic functionality for a @a safe iterator.
40
*
41
* The %_Safe_iterator_base base class implements the functionality
42
* of a safe iterator that is not specific to a particular iterator
43
* type. It contains a pointer back to the sequence it references
44
* along with iterator version information and pointers to form a
45
* doubly-linked list of iterators referenced by the container.
46
*
47
* This class must not perform any operations that can throw an
48
* exception, or the exception guarantees of derived iterators will
49
* be broken.
50
*/
51
class
_Safe_iterator_base
52
{
53
public
:
54
/** The sequence this iterator references; may be NULL to indicate
55
a singular iterator. */
56
_Safe_sequence_base
*
_M_sequence
;
57
58
/** The version number of this iterator. The sentinel value 0 is
59
* used to indicate an invalidated iterator (i.e., one that is
60
* singular because of an operation on the container). This
61
* version number must equal the version number in the sequence
62
* referenced by _M_sequence for the iterator to be
63
* non-singular.
64
*/
65
unsigned
int
_M_version
;
66
67
/** Pointer to the previous iterator in the sequence's list of
68
iterators. Only valid when _M_sequence != NULL. */
69
_Safe_iterator_base
*
_M_prior
;
70
71
/** Pointer to the next iterator in the sequence's list of
72
iterators. Only valid when _M_sequence != NULL. */
73
_Safe_iterator_base
*
_M_next
;
74
75
protected
:
76
/** Initializes the iterator and makes it singular. */
77
_Safe_iterator_base
()
78
:
_M_sequence
(0),
_M_version
(0),
_M_prior
(0),
_M_next
(0)
79
{ }
80
81
/** Initialize the iterator to reference the sequence pointed to
82
* by @p__seq. @p __constant is true when we are initializing a
83
* constant iterator, and false if it is a mutable iterator. Note
84
* that @p __seq may be NULL, in which case the iterator will be
85
* singular. Otherwise, the iterator will reference @p __seq and
86
* be nonsingular.
87
*/
88
_Safe_iterator_base
(
const
_Safe_sequence_base
* __seq,
bool
__constant)
89
:
_M_sequence
(0),
_M_version
(0),
_M_prior
(0),
_M_next
(0)
90
{ this->
_M_attach
(const_cast<_Safe_sequence_base*>(__seq), __constant); }
91
92
/** Initializes the iterator to reference the same sequence that
93
@p __x does. @p __constant is true if this is a constant
94
iterator, and false if it is mutable. */
95
_Safe_iterator_base
(
const
_Safe_iterator_base
& __x,
bool
__constant)
96
:
_M_sequence
(0),
_M_version
(0),
_M_prior
(0),
_M_next
(0)
97
{ this->
_M_attach
(__x.
_M_sequence
, __constant); }
98
99
_Safe_iterator_base
&
100
operator=(
const
_Safe_iterator_base
&);
101
102
explicit
103
_Safe_iterator_base
(
const
_Safe_iterator_base
&);
104
105
~
_Safe_iterator_base
() { this->
_M_detach
(); }
106
107
/** For use in _Safe_iterator. */
108
__gnu_cxx::__mutex&
_M_get_mutex
() throw ();
109
110
public:
111
/** Attaches this iterator to the given sequence, detaching it
112
* from whatever sequence it was attached to originally. If the
113
* new sequence is the NULL pointer, the iterator is left
114
* unattached.
115
*/
116
void
_M_attach
(_Safe_sequence_base* __seq,
bool
__constant);
117
118
/** Likewise, but not thread-safe. */
119
void
_M_attach_single
(_Safe_sequence_base* __seq,
bool
__constant) throw ();
120
121
/** Detach the iterator for whatever sequence it is attached to,
122
* if any.
123
*/
124
void
_M_detach
();
125
126
/** Likewise, but not thread-safe. */
127
void
_M_detach_single
() throw ();
128
129
/** Determines if we are attached to the given sequence. */
130
bool
_M_attached_to
(const
_Safe_sequence_base
* __seq)
const
131
{
return
_M_sequence
== __seq; }
132
133
/** Is this iterator singular? */
134
_GLIBCXX_PURE
bool
_M_singular
()
const
throw ();
135
136
/** Can we compare this iterator to the given iterator @p __x?
137
Returns true if both iterators are nonsingular and reference
138
the same sequence. */
139
_GLIBCXX_PURE
bool
_M_can_compare
(const
_Safe_iterator_base
& __x) const throw ();
140
141
/** Invalidate the iterator, making it singular. */
142
void
143
_M_invalidate
()
144
{
_M_version
= 0; }
145
146
/** Reset all member variables */
147
void
148
_M_reset
() throw ();
149
150
/** Unlink itself */
151
void
152
_M_unlink
() throw ()
153
{
154
if
(
_M_prior
)
155
_M_prior
->
_M_next
=
_M_next
;
156
if
(
_M_next
)
157
_M_next
->
_M_prior
=
_M_prior
;
158
}
159
};
160
161
/**
162
* @brief Base class that supports tracking of iterators that
163
* reference a sequence.
164
*
165
* The %_Safe_sequence_base class provides basic support for
166
* tracking iterators into a sequence. Sequences that track
167
* iterators must derived from %_Safe_sequence_base publicly, so
168
* that safe iterators (which inherit _Safe_iterator_base) can
169
* attach to them. This class contains two linked lists of
170
* iterators, one for constant iterators and one for mutable
171
* iterators, and a version number that allows very fast
172
* invalidation of all iterators that reference the container.
173
*
174
* This class must ensure that no operation on it may throw an
175
* exception, otherwise @a safe sequences may fail to provide the
176
* exception-safety guarantees required by the C++ standard.
177
*/
178
class
_Safe_sequence_base
179
{
180
public
:
181
/// The list of mutable iterators that reference this container
182
_Safe_iterator_base
*
_M_iterators
;
183
184
/// The list of constant iterators that reference this container
185
_Safe_iterator_base
*
_M_const_iterators
;
186
187
/// The container version number. This number may never be 0.
188
mutable
unsigned
int
_M_version
;
189
190
protected
:
191
// Initialize with a version number of 1 and no iterators
192
_Safe_sequence_base
()
193
:
_M_iterators
(0),
_M_const_iterators
(0),
_M_version
(1)
194
{ }
195
196
/** Notify all iterators that reference this sequence that the
197
sequence is being destroyed. */
198
~_Safe_sequence_base
()
199
{ this->
_M_detach_all
(); }
200
201
/** Detach all iterators, leaving them singular. */
202
void
203
_M_detach_all
();
204
205
/** Detach all singular iterators.
206
* @post for all iterators i attached to this sequence,
207
* i->_M_version == _M_version.
208
*/
209
void
210
_M_detach_singular
();
211
212
/** Revalidates all attached singular iterators. This method may
213
* be used to validate iterators that were invalidated before
214
* (but for some reason, such as an exception, need to become
215
* valid again).
216
*/
217
void
218
_M_revalidate_singular
();
219
220
/** Swap this sequence with the given sequence. This operation
221
* also swaps ownership of the iterators, so that when the
222
* operation is complete all iterators that originally referenced
223
* one container now reference the other container.
224
*/
225
void
226
_M_swap
(
_Safe_sequence_base
& __x);
227
228
/** For use in _Safe_sequence. */
229
__gnu_cxx::__mutex&
_M_get_mutex
() throw ();
230
231
public:
232
/** Invalidates all iterators. */
233
void
234
_M_invalidate_all
()
const
235
{
if
(++
_M_version
== 0)
_M_version
= 1; }
236
237
/** Attach an iterator to this sequence. */
238
void
239
_M_attach
(
_Safe_iterator_base
* __it,
bool
__constant);
240
241
/** Likewise but not thread safe. */
242
void
243
_M_attach_single
(
_Safe_iterator_base
* __it,
bool
__constant)
throw
();
244
245
/** Detach an iterator from this sequence */
246
void
247
_M_detach
(
_Safe_iterator_base
* __it);
248
249
/** Likewise but not thread safe. */
250
void
251
_M_detach_single
(
_Safe_iterator_base
* __it)
throw
();
252
};
253
}
// namespace __gnu_debug
254
255
#endif
include
debug
safe_base.h
Generated by
1.8.3.1