debug.hpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. // Debug support for the circular buffer library.
  2. // Copyright (c) 2003-2008 Jan Gaspar
  3. // Use, modification, and distribution is subject to the Boost Software
  4. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #if !defined(BOOST_CIRCULAR_BUFFER_DEBUG_HPP)
  7. #define BOOST_CIRCULAR_BUFFER_DEBUG_HPP
  8. #if defined(_MSC_VER) && _MSC_VER >= 1200
  9. #pragma once
  10. #endif
  11. namespace boost {
  12. namespace cb_details {
  13. #if BOOST_CB_ENABLE_DEBUG
  14. // The value the uninitialized memory is filled with.
  15. const int UNINITIALIZED = 0xcc;
  16. class debug_iterator_registry;
  17. /*!
  18. \class debug_iterator_base
  19. \brief Registers/unregisters iterators into the registry of valid iterators.
  20. This class is intended to be a base class of an iterator.
  21. */
  22. class debug_iterator_base {
  23. private:
  24. // Members
  25. //! Iterator registry.
  26. mutable const debug_iterator_registry* m_registry;
  27. //! Next iterator in the iterator chain.
  28. mutable const debug_iterator_base* m_next;
  29. public:
  30. // Construction/destruction
  31. //! Default constructor.
  32. debug_iterator_base();
  33. //! Constructor taking the iterator registry as a parameter.
  34. debug_iterator_base(const debug_iterator_registry* registry);
  35. //! Copy constructor.
  36. debug_iterator_base(const debug_iterator_base& rhs);
  37. //! Destructor.
  38. ~debug_iterator_base();
  39. // Methods
  40. //! Assign operator.
  41. debug_iterator_base& operator = (const debug_iterator_base& rhs);
  42. //! Is the iterator valid?
  43. bool is_valid(const debug_iterator_registry* registry) const;
  44. //! Invalidate the iterator.
  45. /*!
  46. \note The method is const in order to invalidate const iterators, too.
  47. */
  48. void invalidate() const;
  49. //! Return the next iterator in the iterator chain.
  50. const debug_iterator_base* next() const;
  51. //! Set the next iterator in the iterator chain.
  52. /*!
  53. \note The method is const in order to set a next iterator to a const iterator, too.
  54. */
  55. void set_next(const debug_iterator_base* it) const;
  56. private:
  57. // Helpers
  58. //! Register self as a valid iterator.
  59. void register_self();
  60. //! Unregister self from valid iterators.
  61. void unregister_self();
  62. };
  63. /*!
  64. \class debug_iterator_registry
  65. \brief Registry of valid iterators.
  66. This class is intended to be a base class of a container.
  67. */
  68. class debug_iterator_registry {
  69. //! Pointer to the chain of valid iterators.
  70. mutable const debug_iterator_base* m_iterators;
  71. public:
  72. // Methods
  73. //! Default constructor.
  74. debug_iterator_registry() : m_iterators(0) {}
  75. //! Register an iterator into the list of valid iterators.
  76. /*!
  77. \note The method is const in order to register iterators into const containers, too.
  78. */
  79. void register_iterator(const debug_iterator_base* it) const {
  80. it->set_next(m_iterators);
  81. m_iterators = it;
  82. }
  83. //! Unregister an iterator from the list of valid iterators.
  84. /*!
  85. \note The method is const in order to unregister iterators from const containers, too.
  86. */
  87. void unregister_iterator(const debug_iterator_base* it) const {
  88. const debug_iterator_base* previous = 0;
  89. for (const debug_iterator_base* p = m_iterators; p != it; previous = p, p = p->next()) {}
  90. remove(it, previous);
  91. }
  92. //! Invalidate every iterator pointing to the same element as the iterator passed as a parameter.
  93. template <class Iterator>
  94. void invalidate_iterators(const Iterator& it) {
  95. const debug_iterator_base* previous = 0;
  96. for (const debug_iterator_base* p = m_iterators; p != 0; p = p->next()) {
  97. if (((Iterator*)p)->m_it == it.m_it) {
  98. p->invalidate();
  99. remove(p, previous);
  100. continue;
  101. }
  102. previous = p;
  103. }
  104. }
  105. //! Invalidate all iterators except an iterator poining to the same element as the iterator passed as a parameter.
  106. template <class Iterator>
  107. void invalidate_iterators_except(const Iterator& it) {
  108. const debug_iterator_base* previous = 0;
  109. for (const debug_iterator_base* p = m_iterators; p != 0; p = p->next()) {
  110. if (((Iterator*)p)->m_it != it.m_it) {
  111. p->invalidate();
  112. remove(p, previous);
  113. continue;
  114. }
  115. previous = p;
  116. }
  117. }
  118. //! Invalidate all iterators.
  119. void invalidate_all_iterators() {
  120. for (const debug_iterator_base* p = m_iterators; p != 0; p = p->next())
  121. p->invalidate();
  122. m_iterators = 0;
  123. }
  124. private:
  125. // Helpers
  126. //! Remove the current iterator from the iterator chain.
  127. void remove(const debug_iterator_base* current,
  128. const debug_iterator_base* previous) const {
  129. if (previous == 0)
  130. m_iterators = m_iterators->next();
  131. else
  132. previous->set_next(current->next());
  133. }
  134. };
  135. // Implementation of the debug_iterator_base methods.
  136. inline debug_iterator_base::debug_iterator_base() : m_registry(0), m_next(0) {}
  137. inline debug_iterator_base::debug_iterator_base(const debug_iterator_registry* registry)
  138. : m_registry(registry), m_next(0) {
  139. register_self();
  140. }
  141. inline debug_iterator_base::debug_iterator_base(const debug_iterator_base& rhs)
  142. : m_registry(rhs.m_registry), m_next(0) {
  143. register_self();
  144. }
  145. inline debug_iterator_base::~debug_iterator_base() { unregister_self(); }
  146. inline debug_iterator_base& debug_iterator_base::operator = (const debug_iterator_base& rhs) {
  147. if (m_registry == rhs.m_registry)
  148. return *this;
  149. unregister_self();
  150. m_registry = rhs.m_registry;
  151. register_self();
  152. return *this;
  153. }
  154. inline bool debug_iterator_base::is_valid(const debug_iterator_registry* registry) const {
  155. return m_registry == registry;
  156. }
  157. inline void debug_iterator_base::invalidate() const { m_registry = 0; }
  158. inline const debug_iterator_base* debug_iterator_base::next() const { return m_next; }
  159. inline void debug_iterator_base::set_next(const debug_iterator_base* it) const { m_next = it; }
  160. inline void debug_iterator_base::register_self() {
  161. if (m_registry != 0)
  162. m_registry->register_iterator(this);
  163. }
  164. inline void debug_iterator_base::unregister_self() {
  165. if (m_registry != 0)
  166. m_registry->unregister_iterator(this);
  167. }
  168. #endif // #if BOOST_CB_ENABLE_DEBUG
  169. } // namespace cb_details
  170. } // namespace boost
  171. #endif // #if !defined(BOOST_CIRCULAR_BUFFER_DEBUG_HPP)