Imported Upstream version 1.57.0
[platform/upstream/boost.git] / boost / circular_buffer / debug.hpp
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)
20 namespace std {
21     using ::memset;
22 }
23 #endif
24
25 #endif // BOOST_CB_ENABLE_DEBUG
26 namespace boost {
27
28 namespace cb_details {
29
30 #if BOOST_CB_ENABLE_DEBUG
31
32 // The value the uninitialized memory is filled with.
33 const int UNINITIALIZED = 0xcc;
34
35 template <class T>
36 inline 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
40 template <class T>
41 inline void do_fill_uninitialized_memory(T& /*data*/, std::size_t /*size_in_bytes*/) BOOST_NOEXCEPT {
42     // Do nothing
43 }
44
45
46 class 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 */
54 class debug_iterator_base {
55
56 private:
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
65 public:
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
103 private:
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 */
119 class debug_iterator_registry {
120
121     //! Pointer to the chain of valid iterators.
122     mutable const debug_iterator_base* m_iterators;
123
124 public:
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
184 private:
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
199 inline debug_iterator_base::debug_iterator_base() : m_registry(0), m_next(0) {}
200
201 inline debug_iterator_base::debug_iterator_base(const debug_iterator_registry* registry)
202 : m_registry(registry), m_next(0) {
203     register_self();
204 }
205
206 inline 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
211 inline debug_iterator_base::~debug_iterator_base() { unregister_self(); }
212
213 inline 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
222 inline bool debug_iterator_base::is_valid(const debug_iterator_registry* registry) const {
223     return m_registry == registry;
224 }
225
226 inline void debug_iterator_base::invalidate() const { m_registry = 0; }
227
228 inline const debug_iterator_base* debug_iterator_base::next() const { return m_next; }
229
230 inline void debug_iterator_base::set_next(const debug_iterator_base* it) const { m_next = it; }
231
232 inline void debug_iterator_base::register_self() {
233     if (m_registry != 0)
234         m_registry->register_iterator(this);
235 }
236
237 inline 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)