(root)/
gcc-13.2.0/
libstdc++-v3/
include/
debug/
safe_base.h
       1  // Safe sequence/iterator base implementation  -*- C++ -*-
       2  
       3  // Copyright (C) 2003-2023 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      friend class _Safe_sequence_base;
      53  
      54    public:
      55      /** The sequence this iterator references; may be NULL to indicate
      56  	a singular iterator. */
      57      _Safe_sequence_base*	_M_sequence;
      58  
      59      /** The version number of this iterator. The sentinel value 0 is
      60       *  used to indicate an invalidated iterator (i.e., one that is
      61       *  singular because of an operation on the container). This
      62       *  version number must equal the version number in the sequence
      63       *  referenced by _M_sequence for the iterator to be
      64       *  non-singular.
      65       */
      66      unsigned int		_M_version;
      67  
      68      /** Pointer to the previous iterator in the sequence's list of
      69  	iterators. Only valid when _M_sequence != NULL. */
      70      _Safe_iterator_base*	_M_prior;
      71  
      72      /** Pointer to the next iterator in the sequence's list of
      73  	iterators. Only valid when _M_sequence != NULL. */
      74      _Safe_iterator_base*	_M_next;
      75  
      76    protected:
      77      /** Initializes the iterator and makes it singular. */
      78      _Safe_iterator_base()
      79      : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0)
      80      { }
      81  
      82      /** Initialize the iterator to reference the sequence pointed to
      83       *  by @p __seq. @p __constant is true when we are initializing a
      84       *  constant iterator, and false if it is a mutable iterator. Note
      85       *  that @p __seq may be NULL, in which case the iterator will be
      86       *  singular. Otherwise, the iterator will reference @p __seq and
      87       *  be nonsingular.
      88       */
      89      _Safe_iterator_base(const _Safe_sequence_base* __seq, bool __constant)
      90      : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0)
      91      { this->_M_attach(const_cast<_Safe_sequence_base*>(__seq), __constant); }
      92  
      93      /** Initializes the iterator to reference the same sequence that
      94  	@p __x does. @p __constant is true if this is a constant
      95  	iterator, and false if it is mutable. */
      96      _Safe_iterator_base(const _Safe_iterator_base& __x, bool __constant)
      97      : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0)
      98      { this->_M_attach(__x._M_sequence, __constant); }
      99  
     100      ~_Safe_iterator_base() { this->_M_detach(); }
     101  
     102      /** For use in _Safe_iterator. */
     103      __gnu_cxx::__mutex&
     104      _M_get_mutex() throw ();
     105  
     106      /** Attaches this iterator to the given sequence, detaching it
     107       *	from whatever sequence it was attached to originally. If the
     108       *	new sequence is the NULL pointer, the iterator is left
     109       *	unattached.
     110       */
     111      void
     112      _M_attach(_Safe_sequence_base* __seq, bool __constant);
     113  
     114      /** Likewise, but not thread-safe. */
     115      void
     116      _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw ();
     117  
     118      /** Detach the iterator for whatever sequence it is attached to,
     119       *	if any.
     120      */
     121      void
     122      _M_detach();
     123  
     124    public:
     125      /** Likewise, but not thread-safe. */
     126      void
     127      _M_detach_single() throw ();
     128  
     129      /** Determines if we are attached to the given sequence. */
     130      bool
     131      _M_attached_to(const _Safe_sequence_base* __seq) const
     132      { return _M_sequence == __seq; }
     133  
     134      /** Is this iterator singular? */
     135      _GLIBCXX_PURE bool
     136      _M_singular() const throw ();
     137  
     138      /** Can we compare this iterator to the given iterator @p __x?
     139  	Returns true if both iterators are nonsingular and reference
     140  	the same sequence. */
     141      _GLIBCXX_PURE bool
     142      _M_can_compare(const _Safe_iterator_base& __x) const throw ();
     143  
     144      /** Invalidate the iterator, making it singular. */
     145      void
     146      _M_invalidate()
     147      { _M_version = 0; }
     148  
     149      /** Reset all member variables */
     150      void
     151      _M_reset() throw ();
     152  
     153      /** Unlink itself */
     154      void
     155      _M_unlink() throw ()
     156      {
     157        if (_M_prior)
     158  	_M_prior->_M_next = _M_next;
     159        if (_M_next)
     160  	_M_next->_M_prior = _M_prior;
     161      }
     162    };
     163  
     164    /** Iterators that derive from _Safe_iterator_base can be determined singular
     165     *  or non-singular.
     166     **/
     167    inline bool
     168    __check_singular_aux(const _Safe_iterator_base* __x)
     169    { return __x->_M_singular(); }
     170  
     171    /**
     172     * @brief Base class that supports tracking of iterators that
     173     * reference a sequence.
     174     *
     175     * The %_Safe_sequence_base class provides basic support for
     176     * tracking iterators into a sequence. Sequences that track
     177     * iterators must derived from %_Safe_sequence_base publicly, so
     178     * that safe iterators (which inherit _Safe_iterator_base) can
     179     * attach to them. This class contains two linked lists of
     180     * iterators, one for constant iterators and one for mutable
     181     * iterators, and a version number that allows very fast
     182     * invalidation of all iterators that reference the container.
     183     *
     184     * This class must ensure that no operation on it may throw an
     185     * exception, otherwise @a safe sequences may fail to provide the
     186     * exception-safety guarantees required by the C++ standard.
     187     */
     188    class _Safe_sequence_base
     189    {
     190      friend class _Safe_iterator_base;
     191  
     192    public:
     193      /// The list of mutable iterators that reference this container
     194      _Safe_iterator_base* _M_iterators;
     195  
     196      /// The list of constant iterators that reference this container
     197      _Safe_iterator_base* _M_const_iterators;
     198  
     199      /// The container version number. This number may never be 0.
     200      mutable unsigned int _M_version;
     201  
     202    protected:
     203      // Initialize with a version number of 1 and no iterators
     204      _Safe_sequence_base() _GLIBCXX_NOEXCEPT
     205      : _M_iterators(0), _M_const_iterators(0), _M_version(1)
     206      { }
     207  
     208  #if __cplusplus >= 201103L
     209      _Safe_sequence_base(const _Safe_sequence_base&) noexcept
     210      : _Safe_sequence_base() { }
     211  
     212      // Move constructor swap iterators.
     213      _Safe_sequence_base(_Safe_sequence_base&& __seq) noexcept
     214      : _Safe_sequence_base()
     215      { _M_swap(__seq); }
     216  #endif
     217  
     218      /** Notify all iterators that reference this sequence that the
     219  	sequence is being destroyed. */
     220      ~_Safe_sequence_base()
     221      { this->_M_detach_all(); }
     222  
     223      /** Detach all iterators, leaving them singular. */
     224      void
     225      _M_detach_all();
     226  
     227      /** Detach all singular iterators.
     228       *  @post for all iterators i attached to this sequence,
     229       *   i->_M_version == _M_version.
     230       */
     231      void
     232      _M_detach_singular();
     233  
     234      /** Revalidates all attached singular iterators.  This method may
     235       *  be used to validate iterators that were invalidated before
     236       *  (but for some reason, such as an exception, need to become
     237       *  valid again).
     238       */
     239      void
     240      _M_revalidate_singular();
     241  
     242      /** Swap this sequence with the given sequence. This operation
     243       *  also swaps ownership of the iterators, so that when the
     244       *  operation is complete all iterators that originally referenced
     245       *  one container now reference the other container.
     246       */
     247      void
     248      _M_swap(_Safe_sequence_base& __x) _GLIBCXX_USE_NOEXCEPT;
     249  
     250      /** For use in _Safe_sequence. */
     251      __gnu_cxx::__mutex&
     252      _M_get_mutex() throw ();
     253  
     254      /** Invalidates all iterators. */
     255      void
     256      _M_invalidate_all() const
     257      { if (++_M_version == 0) _M_version = 1; }
     258  
     259    private:
     260      /** Attach an iterator to this sequence. */
     261      void
     262      _M_attach(_Safe_iterator_base* __it, bool __constant);
     263  
     264      /** Likewise but not thread safe. */
     265      void
     266      _M_attach_single(_Safe_iterator_base* __it, bool __constant) throw ();
     267  
     268      /** Detach an iterator from this sequence */
     269      void
     270      _M_detach(_Safe_iterator_base* __it);
     271  
     272      /** Likewise but not thread safe. */
     273      void
     274      _M_detach_single(_Safe_iterator_base* __it) throw ();
     275    };
     276  } // namespace __gnu_debug
     277  
     278  #endif