1// Debug support for the circular buffer library.
2
3// Copyright (c) 2003-2008 Jan Gaspar
4
5// Use, modification, and distribution is subject to the Boost Software
6// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8
9#if !defined(BOOST_CIRCULAR_BUFFER_DEBUG_HPP)
10#define BOOST_CIRCULAR_BUFFER_DEBUG_HPP
11
12#if defined(_MSC_VER)
13 #pragma once
14#endif
15
16#if BOOST_CB_ENABLE_DEBUG
17#include <cstring>
18
19#if defined(BOOST_NO_STDC_NAMESPACE)
20namespace std {
21 using ::memset;
22}
23#endif
24
25#endif // BOOST_CB_ENABLE_DEBUG
26namespace boost {
27
28namespace cb_details {
29
30#if BOOST_CB_ENABLE_DEBUG
31
32// The value the uninitialized memory is filled with.
33const int UNINITIALIZED = 0xcc;
34
35template <class T>
36inline void do_fill_uninitialized_memory(T* data, std::size_t size_in_bytes) BOOST_NOEXCEPT {
37 std::memset(static_cast<void*>(data), UNINITIALIZED, size_in_bytes);
38}
39
40template <class T>
41inline void do_fill_uninitialized_memory(T& /*data*/, std::size_t /*size_in_bytes*/) BOOST_NOEXCEPT {
42 // Do nothing
43}
44
45
46class debug_iterator_registry;
47
48/*!
49 \class debug_iterator_base
50 \brief Registers/unregisters iterators into the registry of valid iterators.
51
52 This class is intended to be a base class of an iterator.
53*/
54class debug_iterator_base {
55
56private:
57// Members
58
59 //! Iterator registry.
60 mutable const debug_iterator_registry* m_registry;
61
62 //! Next iterator in the iterator chain.
63 mutable const debug_iterator_base* m_next;
64
65public:
66// Construction/destruction
67
68 //! Default constructor.
69 debug_iterator_base();
70
71 //! Constructor taking the iterator registry as a parameter.
72 debug_iterator_base(const debug_iterator_registry* registry);
73
74 //! Copy constructor.
75 debug_iterator_base(const debug_iterator_base& rhs);
76
77 //! Destructor.
78 ~debug_iterator_base();
79
80// Methods
81
82 //! Assign operator.
83 debug_iterator_base& operator = (const debug_iterator_base& rhs);
84
85 //! Is the iterator valid?
86 bool is_valid(const debug_iterator_registry* registry) const;
87
88 //! Invalidate the iterator.
89 /*!
90 \note The method is const in order to invalidate const iterators, too.
91 */
92 void invalidate() const;
93
94 //! Return the next iterator in the iterator chain.
95 const debug_iterator_base* next() const;
96
97 //! Set the next iterator in the iterator chain.
98 /*!
99 \note The method is const in order to set a next iterator to a const iterator, too.
100 */
101 void set_next(const debug_iterator_base* it) const;
102
103private:
104// Helpers
105
106 //! Register self as a valid iterator.
107 void register_self();
108
109 //! Unregister self from valid iterators.
110 void unregister_self();
111};
112
113/*!
114 \class debug_iterator_registry
115 \brief Registry of valid iterators.
116
117 This class is intended to be a base class of a container.
118*/
119class debug_iterator_registry {
120
121 //! Pointer to the chain of valid iterators.
122 mutable const debug_iterator_base* m_iterators;
123
124public:
125// Methods
126
127 //! Default constructor.
128 debug_iterator_registry() : m_iterators(0) {}
129
130 //! Register an iterator into the list of valid iterators.
131 /*!
132 \note The method is const in order to register iterators into const containers, too.
133 */
134 void register_iterator(const debug_iterator_base* it) const {
135 it->set_next(m_iterators);
136 m_iterators = it;
137 }
138
139 //! Unregister an iterator from the list of valid iterators.
140 /*!
141 \note The method is const in order to unregister iterators from const containers, too.
142 */
143 void unregister_iterator(const debug_iterator_base* it) const {
144 const debug_iterator_base* previous = 0;
145 for (const debug_iterator_base* p = m_iterators; p != it; previous = p, p = p->next()) {}
146 remove(it, previous);
147 }
148
149 //! Invalidate every iterator pointing to the same element as the iterator passed as a parameter.
150 template <class Iterator>
151 void invalidate_iterators(const Iterator& it) {
152 const debug_iterator_base* previous = 0;
153 for (const debug_iterator_base* p = m_iterators; p != 0; p = p->next()) {
154 if (((Iterator*)p)->m_it == it.m_it) {
155 p->invalidate();
156 remove(p, previous);
157 continue;
158 }
159 previous = p;
160 }
161 }
162
163 //! Invalidate all iterators except an iterator poining to the same element as the iterator passed as a parameter.
164 template <class Iterator>
165 void invalidate_iterators_except(const Iterator& it) {
166 const debug_iterator_base* previous = 0;
167 for (const debug_iterator_base* p = m_iterators; p != 0; p = p->next()) {
168 if (((Iterator*)p)->m_it != it.m_it) {
169 p->invalidate();
170 remove(p, previous);
171 continue;
172 }
173 previous = p;
174 }
175 }
176
177 //! Invalidate all iterators.
178 void invalidate_all_iterators() {
179 for (const debug_iterator_base* p = m_iterators; p != 0; p = p->next())
180 p->invalidate();
181 m_iterators = 0;
182 }
183
184private:
185// Helpers
186
187 //! Remove the current iterator from the iterator chain.
188 void remove(const debug_iterator_base* current,
189 const debug_iterator_base* previous) const {
190 if (previous == 0)
191 m_iterators = m_iterators->next();
192 else
193 previous->set_next(current->next());
194 }
195};
196
197// Implementation of the debug_iterator_base methods.
198
199inline debug_iterator_base::debug_iterator_base() : m_registry(0), m_next(0) {}
200
201inline debug_iterator_base::debug_iterator_base(const debug_iterator_registry* registry)
202: m_registry(registry), m_next(0) {
203 register_self();
204}
205
206inline debug_iterator_base::debug_iterator_base(const debug_iterator_base& rhs)
207: m_registry(rhs.m_registry), m_next(0) {
208 register_self();
209}
210
211inline debug_iterator_base::~debug_iterator_base() { unregister_self(); }
212
213inline debug_iterator_base& debug_iterator_base::operator = (const debug_iterator_base& rhs) {
214 if (m_registry == rhs.m_registry)
215 return *this;
216 unregister_self();
217 m_registry = rhs.m_registry;
218 register_self();
219 return *this;
220}
221
222inline bool debug_iterator_base::is_valid(const debug_iterator_registry* registry) const {
223 return m_registry == registry;
224}
225
226inline void debug_iterator_base::invalidate() const { m_registry = 0; }
227
228inline const debug_iterator_base* debug_iterator_base::next() const { return m_next; }
229
230inline void debug_iterator_base::set_next(const debug_iterator_base* it) const { m_next = it; }
231
232inline void debug_iterator_base::register_self() {
233 if (m_registry != 0)
234 m_registry->register_iterator(this);
235}
236
237inline void debug_iterator_base::unregister_self() {
238 if (m_registry != 0)
239 m_registry->unregister_iterator(this);
240}
241
242#endif // #if BOOST_CB_ENABLE_DEBUG
243
244} // namespace cb_details
245
246} // namespace boost
247
248#endif // #if !defined(BOOST_CIRCULAR_BUFFER_DEBUG_HPP)
249

source code of include/boost/circular_buffer/debug.hpp