1  // Safe container/iterator base implementation  -*- C++ -*-
       2  
       3  // Copyright (C) 2011-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_unordered_base.h
      26   *  This file is a GNU debug extension to the Standard C++ Library.
      27   */
      28  
      29  #ifndef _GLIBCXX_DEBUG_SAFE_UNORDERED_BASE_H
      30  #define _GLIBCXX_DEBUG_SAFE_UNORDERED_BASE_H 1
      31  
      32  #include <debug/safe_base.h>
      33  
      34  namespace __gnu_debug
      35  {
      36    class _Safe_unordered_container_base;
      37  
      38    /** \brief Basic functionality for a @a safe iterator.
      39     *
      40     *  The %_Safe_local_iterator_base base class implements the functionality
      41     *  of a safe local iterator that is not specific to a particular iterator
      42     *  type. It contains a pointer back to the container it references
      43     *  along with iterator version information and pointers to form a
      44     *  doubly-linked list of local 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_local_iterator_base : public _Safe_iterator_base
      51    {
      52    protected:
      53      /** Initializes the iterator and makes it singular. */
      54      _Safe_local_iterator_base()
      55      { }
      56  
      57      /** Initialize the iterator to reference the container pointed to
      58       *  by @p __seq. @p __constant is true when we are initializing a
      59       *  constant local iterator, and false if it is a mutable local iterator.
      60       *  Note that @p __seq may be NULL, in which case the iterator will be
      61       *  singular. Otherwise, the iterator will reference @p __seq and
      62       *  be nonsingular.
      63       */
      64      _Safe_local_iterator_base(const _Safe_sequence_base* __seq, bool __constant)
      65      { this->_M_attach(const_cast<_Safe_sequence_base*>(__seq), __constant); }
      66  
      67      /** Initializes the iterator to reference the same container that
      68  	@p __x does. @p __constant is true if this is a constant
      69  	iterator, and false if it is mutable. */
      70      _Safe_local_iterator_base(const _Safe_local_iterator_base& __x,
      71  			      bool __constant)
      72      { this->_M_attach(__x._M_sequence, __constant); }
      73  
      74      ~_Safe_local_iterator_base() { this->_M_detach(); }
      75  
      76      _Safe_unordered_container_base*
      77      _M_get_container() const noexcept;
      78  
      79      /** Attaches this iterator to the given container, detaching it
      80       *	from whatever container it was attached to originally. If the
      81       *	new container is the NULL pointer, the iterator is left
      82       *	unattached.
      83       */
      84      void
      85      _M_attach(_Safe_sequence_base* __seq, bool __constant);
      86  
      87      /** Likewise, but not thread-safe. */
      88      void
      89      _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw ();
      90  
      91      /** Detach the iterator for whatever container it is attached to,
      92       *	if any.
      93      */
      94      void
      95      _M_detach();
      96  
      97      /** Likewise, but not thread-safe. */
      98      void
      99      _M_detach_single() throw ();
     100    };
     101  
     102    /**
     103     * @brief Base class that supports tracking of local iterators that
     104     * reference an unordered container.
     105     *
     106     * The %_Safe_unordered_container_base class provides basic support for
     107     * tracking iterators into an unordered container. Containers that track
     108     * iterators must derived from %_Safe_unordered_container_base publicly, so
     109     * that safe iterators (which inherit _Safe_iterator_base) can
     110     * attach to them. This class contains four linked lists of
     111     * iterators, one for constant iterators, one for mutable
     112     * iterators, one for constant local iterators, one for mutable local
     113     * iterators and a version number that allows very fast
     114     * invalidation of all iterators that reference the container.
     115     *
     116     * This class must ensure that no operation on it may throw an
     117     * exception, otherwise @a safe containers may fail to provide the
     118     * exception-safety guarantees required by the C++ standard.
     119     */
     120    class _Safe_unordered_container_base : public _Safe_sequence_base
     121    {
     122      friend class _Safe_local_iterator_base;
     123      typedef _Safe_sequence_base _Base;
     124  
     125    public:
     126      /// The list of mutable local iterators that reference this container
     127      _Safe_iterator_base* _M_local_iterators;
     128  
     129      /// The list of constant local iterators that reference this container
     130      _Safe_iterator_base* _M_const_local_iterators;
     131  
     132    protected:
     133      // Initialize with a version number of 1 and no iterators
     134      _Safe_unordered_container_base() noexcept
     135      : _M_local_iterators(nullptr), _M_const_local_iterators(nullptr)
     136      { }
     137  
     138      // Copy constructor does not copy iterators.
     139      _Safe_unordered_container_base(const _Safe_unordered_container_base&)
     140      noexcept
     141      : _Safe_unordered_container_base() { }
     142  
     143      // When moved unordered containers iterators are swapped.
     144      _Safe_unordered_container_base(_Safe_unordered_container_base&& __x)
     145      noexcept
     146      : _Safe_unordered_container_base()
     147      { this->_M_swap(__x); }
     148  
     149      /** Notify all iterators that reference this container that the
     150  	container is being destroyed. */
     151      ~_Safe_unordered_container_base() noexcept
     152      { this->_M_detach_all(); }
     153  
     154      /** Detach all iterators, leaving them singular. */
     155      void
     156      _M_detach_all();
     157  
     158      /** Swap this container with the given container. This operation
     159       *  also swaps ownership of the iterators, so that when the
     160       *  operation is complete all iterators that originally referenced
     161       *  one container now reference the other container.
     162       */
     163      void
     164      _M_swap(_Safe_unordered_container_base& __x) noexcept;
     165  
     166    private:
     167      /** Attach an iterator to this container. */
     168      void
     169      _M_attach_local(_Safe_iterator_base* __it, bool __constant);
     170  
     171      /** Likewise but not thread safe. */
     172      void
     173      _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) throw ();
     174  
     175      /** Detach an iterator from this container */
     176      void
     177      _M_detach_local(_Safe_iterator_base* __it);
     178  
     179      /** Likewise but not thread safe. */
     180      void
     181      _M_detach_local_single(_Safe_iterator_base* __it) throw ();
     182    };
     183  } // namespace __gnu_debug
     184  
     185  #endif