Chris@16: // Debug support for the circular buffer library. Chris@16: Chris@16: // Copyright (c) 2003-2008 Jan Gaspar Chris@16: Chris@16: // Use, modification, and distribution is subject to the Boost Software Chris@16: // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #if !defined(BOOST_CIRCULAR_BUFFER_DEBUG_HPP) Chris@16: #define BOOST_CIRCULAR_BUFFER_DEBUG_HPP Chris@16: Chris@101: #if defined(_MSC_VER) Chris@16: #pragma once Chris@16: #endif Chris@16: Chris@101: #if BOOST_CB_ENABLE_DEBUG Chris@101: #include Chris@101: Chris@101: #if defined(BOOST_NO_STDC_NAMESPACE) Chris@101: namespace std { Chris@101: using ::memset; Chris@101: } Chris@101: #endif Chris@101: Chris@101: #endif // BOOST_CB_ENABLE_DEBUG Chris@16: namespace boost { Chris@16: Chris@16: namespace cb_details { Chris@16: Chris@16: #if BOOST_CB_ENABLE_DEBUG Chris@16: Chris@16: // The value the uninitialized memory is filled with. Chris@16: const int UNINITIALIZED = 0xcc; Chris@16: Chris@101: template Chris@101: inline void do_fill_uninitialized_memory(T* data, std::size_t size_in_bytes) BOOST_NOEXCEPT { Chris@101: std::memset(static_cast(data), UNINITIALIZED, size_in_bytes); Chris@101: } Chris@101: Chris@101: template Chris@101: inline void do_fill_uninitialized_memory(T& /*data*/, std::size_t /*size_in_bytes*/) BOOST_NOEXCEPT { Chris@101: // Do nothing Chris@101: } Chris@101: Chris@101: Chris@16: class debug_iterator_registry; Chris@16: Chris@16: /*! Chris@16: \class debug_iterator_base Chris@16: \brief Registers/unregisters iterators into the registry of valid iterators. Chris@16: Chris@16: This class is intended to be a base class of an iterator. Chris@16: */ Chris@16: class debug_iterator_base { Chris@16: Chris@16: private: Chris@16: // Members Chris@16: Chris@16: //! Iterator registry. Chris@16: mutable const debug_iterator_registry* m_registry; Chris@16: Chris@16: //! Next iterator in the iterator chain. Chris@16: mutable const debug_iterator_base* m_next; Chris@16: Chris@16: public: Chris@16: // Construction/destruction Chris@16: Chris@16: //! Default constructor. Chris@16: debug_iterator_base(); Chris@16: Chris@16: //! Constructor taking the iterator registry as a parameter. Chris@16: debug_iterator_base(const debug_iterator_registry* registry); Chris@16: Chris@16: //! Copy constructor. Chris@16: debug_iterator_base(const debug_iterator_base& rhs); Chris@16: Chris@16: //! Destructor. Chris@16: ~debug_iterator_base(); Chris@16: Chris@16: // Methods Chris@16: Chris@16: //! Assign operator. Chris@16: debug_iterator_base& operator = (const debug_iterator_base& rhs); Chris@16: Chris@16: //! Is the iterator valid? Chris@16: bool is_valid(const debug_iterator_registry* registry) const; Chris@16: Chris@16: //! Invalidate the iterator. Chris@16: /*! Chris@16: \note The method is const in order to invalidate const iterators, too. Chris@16: */ Chris@16: void invalidate() const; Chris@16: Chris@16: //! Return the next iterator in the iterator chain. Chris@16: const debug_iterator_base* next() const; Chris@16: Chris@16: //! Set the next iterator in the iterator chain. Chris@16: /*! Chris@16: \note The method is const in order to set a next iterator to a const iterator, too. Chris@16: */ Chris@16: void set_next(const debug_iterator_base* it) const; Chris@16: Chris@16: private: Chris@16: // Helpers Chris@16: Chris@16: //! Register self as a valid iterator. Chris@16: void register_self(); Chris@16: Chris@16: //! Unregister self from valid iterators. Chris@16: void unregister_self(); Chris@16: }; Chris@16: Chris@16: /*! Chris@16: \class debug_iterator_registry Chris@16: \brief Registry of valid iterators. Chris@16: Chris@16: This class is intended to be a base class of a container. Chris@16: */ Chris@16: class debug_iterator_registry { Chris@16: Chris@16: //! Pointer to the chain of valid iterators. Chris@16: mutable const debug_iterator_base* m_iterators; Chris@16: Chris@16: public: Chris@16: // Methods Chris@16: Chris@16: //! Default constructor. Chris@16: debug_iterator_registry() : m_iterators(0) {} Chris@16: Chris@16: //! Register an iterator into the list of valid iterators. Chris@16: /*! Chris@16: \note The method is const in order to register iterators into const containers, too. Chris@16: */ Chris@16: void register_iterator(const debug_iterator_base* it) const { Chris@16: it->set_next(m_iterators); Chris@16: m_iterators = it; Chris@16: } Chris@16: Chris@16: //! Unregister an iterator from the list of valid iterators. Chris@16: /*! Chris@16: \note The method is const in order to unregister iterators from const containers, too. Chris@16: */ Chris@16: void unregister_iterator(const debug_iterator_base* it) const { Chris@16: const debug_iterator_base* previous = 0; Chris@16: for (const debug_iterator_base* p = m_iterators; p != it; previous = p, p = p->next()) {} Chris@16: remove(it, previous); Chris@16: } Chris@16: Chris@16: //! Invalidate every iterator pointing to the same element as the iterator passed as a parameter. Chris@16: template Chris@16: void invalidate_iterators(const Iterator& it) { Chris@16: const debug_iterator_base* previous = 0; Chris@16: for (const debug_iterator_base* p = m_iterators; p != 0; p = p->next()) { Chris@16: if (((Iterator*)p)->m_it == it.m_it) { Chris@16: p->invalidate(); Chris@16: remove(p, previous); Chris@16: continue; Chris@16: } Chris@16: previous = p; Chris@16: } Chris@16: } Chris@16: Chris@16: //! Invalidate all iterators except an iterator poining to the same element as the iterator passed as a parameter. Chris@16: template Chris@16: void invalidate_iterators_except(const Iterator& it) { Chris@16: const debug_iterator_base* previous = 0; Chris@16: for (const debug_iterator_base* p = m_iterators; p != 0; p = p->next()) { Chris@16: if (((Iterator*)p)->m_it != it.m_it) { Chris@16: p->invalidate(); Chris@16: remove(p, previous); Chris@16: continue; Chris@16: } Chris@16: previous = p; Chris@16: } Chris@16: } Chris@16: Chris@16: //! Invalidate all iterators. Chris@16: void invalidate_all_iterators() { Chris@16: for (const debug_iterator_base* p = m_iterators; p != 0; p = p->next()) Chris@16: p->invalidate(); Chris@16: m_iterators = 0; Chris@16: } Chris@16: Chris@16: private: Chris@16: // Helpers Chris@16: Chris@16: //! Remove the current iterator from the iterator chain. Chris@16: void remove(const debug_iterator_base* current, Chris@16: const debug_iterator_base* previous) const { Chris@16: if (previous == 0) Chris@16: m_iterators = m_iterators->next(); Chris@16: else Chris@16: previous->set_next(current->next()); Chris@16: } Chris@16: }; Chris@16: Chris@16: // Implementation of the debug_iterator_base methods. Chris@16: Chris@16: inline debug_iterator_base::debug_iterator_base() : m_registry(0), m_next(0) {} Chris@16: Chris@16: inline debug_iterator_base::debug_iterator_base(const debug_iterator_registry* registry) Chris@16: : m_registry(registry), m_next(0) { Chris@16: register_self(); Chris@16: } Chris@16: Chris@16: inline debug_iterator_base::debug_iterator_base(const debug_iterator_base& rhs) Chris@16: : m_registry(rhs.m_registry), m_next(0) { Chris@16: register_self(); Chris@16: } Chris@16: Chris@16: inline debug_iterator_base::~debug_iterator_base() { unregister_self(); } Chris@16: Chris@16: inline debug_iterator_base& debug_iterator_base::operator = (const debug_iterator_base& rhs) { Chris@16: if (m_registry == rhs.m_registry) Chris@16: return *this; Chris@16: unregister_self(); Chris@16: m_registry = rhs.m_registry; Chris@16: register_self(); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: inline bool debug_iterator_base::is_valid(const debug_iterator_registry* registry) const { Chris@16: return m_registry == registry; Chris@16: } Chris@16: Chris@16: inline void debug_iterator_base::invalidate() const { m_registry = 0; } Chris@16: Chris@16: inline const debug_iterator_base* debug_iterator_base::next() const { return m_next; } Chris@16: Chris@16: inline void debug_iterator_base::set_next(const debug_iterator_base* it) const { m_next = it; } Chris@16: Chris@16: inline void debug_iterator_base::register_self() { Chris@16: if (m_registry != 0) Chris@16: m_registry->register_iterator(this); Chris@16: } Chris@16: Chris@16: inline void debug_iterator_base::unregister_self() { Chris@16: if (m_registry != 0) Chris@16: m_registry->unregister_iterator(this); Chris@16: } Chris@16: Chris@16: #endif // #if BOOST_CB_ENABLE_DEBUG Chris@16: Chris@16: } // namespace cb_details Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: #endif // #if !defined(BOOST_CIRCULAR_BUFFER_DEBUG_HPP)