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