1132720Skan// Safe sequence implementation  -*- C++ -*-
2132720Skan
3169691Skan// Copyright (C) 2003, 2004, 2005, 2006
4132720Skan// Free Software Foundation, Inc.
5132720Skan//
6132720Skan// This file is part of the GNU ISO C++ Library.  This library is free
7132720Skan// software; you can redistribute it and/or modify it under the
8132720Skan// terms of the GNU General Public License as published by the
9132720Skan// Free Software Foundation; either version 2, or (at your option)
10132720Skan// any later version.
11132720Skan
12132720Skan// This library is distributed in the hope that it will be useful,
13132720Skan// but WITHOUT ANY WARRANTY; without even the implied warranty of
14132720Skan// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15132720Skan// GNU General Public License for more details.
16132720Skan
17132720Skan// You should have received a copy of the GNU General Public License along
18132720Skan// with this library; see the file COPYING.  If not, write to the Free
19169691Skan// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20132720Skan// USA.
21132720Skan
22132720Skan// As a special exception, you may use this file as part of a free software
23132720Skan// library without restriction.  Specifically, if other files instantiate
24132720Skan// templates or use macros or inline functions from this file, or you compile
25132720Skan// this file and link it with other files to produce an executable, this
26132720Skan// file does not by itself cause the resulting executable to be covered by
27132720Skan// the GNU General Public License.  This exception does not however
28132720Skan// invalidate any other reasons why the executable file might be covered by
29132720Skan// the GNU General Public License.
30132720Skan
31169691Skan/** @file debug/safe_sequence.h
32169691Skan *  This file is a GNU debug extension to the Standard C++ Library.
33169691Skan */
34169691Skan
35132720Skan#ifndef _GLIBCXX_DEBUG_SAFE_SEQUENCE_H
36132720Skan#define _GLIBCXX_DEBUG_SAFE_SEQUENCE_H 1
37132720Skan
38132720Skan#include <debug/debug.h>
39169691Skan#include <debug/macros.h>
40169691Skan#include <debug/functions.h>
41132720Skan#include <debug/safe_base.h>
42132720Skan
43132720Skannamespace __gnu_debug
44132720Skan{
45132720Skan  template<typename _Iterator, typename _Sequence>
46132720Skan    class _Safe_iterator;
47132720Skan
48132720Skan  /** A simple function object that returns true if the passed-in
49132720Skan   *  value is not equal to the stored value. It saves typing over
50132720Skan   *  using both bind1st and not_equal.
51132720Skan   */
52132720Skan  template<typename _Type>
53132720Skan    class _Not_equal_to
54132720Skan    {
55132720Skan      _Type __value;
56132720Skan
57132720Skan    public:
58132720Skan      explicit _Not_equal_to(const _Type& __v) : __value(__v) { }
59132720Skan
60132720Skan      bool
61132720Skan      operator()(const _Type& __x) const
62132720Skan      { return __value != __x; }
63132720Skan    };
64132720Skan
65132720Skan  /** A function object that returns true when the given random access
66132720Skan      iterator is at least @c n steps away from the given iterator. */
67132720Skan  template<typename _Iterator>
68132720Skan    class _After_nth_from
69132720Skan    {
70132720Skan      typedef typename std::iterator_traits<_Iterator>::difference_type
71132720Skan      difference_type;
72132720Skan
73132720Skan      _Iterator _M_base;
74132720Skan      difference_type _M_n;
75132720Skan
76132720Skan    public:
77132720Skan      _After_nth_from(const difference_type& __n, const _Iterator& __base)
78132720Skan      : _M_base(__base), _M_n(__n) { }
79132720Skan
80132720Skan      bool
81132720Skan      operator()(const _Iterator& __x) const
82132720Skan      { return __x - _M_base >= _M_n; }
83132720Skan    };
84132720Skan
85132720Skan  /**
86132720Skan   * @brief Base class for constructing a "safe" sequence type that
87132720Skan   * tracks iterators that reference it.
88132720Skan   *
89132720Skan   * The class template %_Safe_sequence simplifies the construction of
90132720Skan   * "safe" sequences that track the iterators that reference the
91132720Skan   * sequence, so that the iterators are notified of changes in the
92132720Skan   * sequence that may affect their operation, e.g., if the container
93132720Skan   * invalidates its iterators or is destructed. This class template
94132720Skan   * may only be used by deriving from it and passing the name of the
95132720Skan   * derived class as its template parameter via the curiously
96132720Skan   * recurring template pattern. The derived class must have @c
97132720Skan   * iterator and @const_iterator types that are instantiations of
98132720Skan   * class template _Safe_iterator for this sequence. Iterators will
99132720Skan   * then be tracked automatically.
100132720Skan   */
101132720Skan  template<typename _Sequence>
102132720Skan    class _Safe_sequence : public _Safe_sequence_base
103132720Skan    {
104132720Skan    public:
105132720Skan      /** Invalidates all iterators @c x that reference this sequence,
106132720Skan	  are not singular, and for which @c pred(x) returns @c
107132720Skan	  true. The user of this routine should be careful not to make
108132720Skan	  copies of the iterators passed to @p pred, as the copies may
109132720Skan	  interfere with the invalidation. */
110132720Skan      template<typename _Predicate>
111132720Skan        void
112132720Skan        _M_invalidate_if(_Predicate __pred);
113132720Skan
114132720Skan      /** Transfers all iterators that reference this memory location
115132720Skan	  to this sequence from whatever sequence they are attached
116132720Skan	  to. */
117132720Skan      template<typename _Iterator>
118132720Skan        void
119132720Skan        _M_transfer_iter(const _Safe_iterator<_Iterator, _Sequence>& __x);
120132720Skan    };
121132720Skan
122132720Skan  template<typename _Sequence>
123132720Skan    template<typename _Predicate>
124132720Skan      void
125132720Skan      _Safe_sequence<_Sequence>::
126132720Skan      _M_invalidate_if(_Predicate __pred)
127132720Skan      {
128132720Skan        typedef typename _Sequence::iterator iterator;
129132720Skan        typedef typename _Sequence::const_iterator const_iterator;
130132720Skan
131169691Skan	__gnu_cxx::__scoped_lock sentry(this->_M_get_mutex());
132169691Skan        for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
133169691Skan	  {
134169691Skan	    iterator* __victim = static_cast<iterator*>(__iter);
135169691Skan	    __iter = __iter->_M_next;
136169691Skan	    if (!__victim->_M_singular())
137169691Skan	      {
138169691Skan		if (__pred(__victim->base()))
139169691Skan		  __victim->_M_invalidate_single();
140169691Skan	      }
141169691Skan	  }
142132720Skan
143169691Skan        for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
144169691Skan	  {
145169691Skan	    const_iterator* __victim = static_cast<const_iterator*>(__iter2);
146169691Skan	    __iter2 = __iter2->_M_next;
147169691Skan	    if (!__victim->_M_singular())
148169691Skan	      {
149169691Skan		if (__pred(__victim->base()))
150169691Skan		  __victim->_M_invalidate_single();
151169691Skan	      }
152169691Skan	  }
153132720Skan      }
154132720Skan
155132720Skan  template<typename _Sequence>
156132720Skan    template<typename _Iterator>
157132720Skan      void
158132720Skan      _Safe_sequence<_Sequence>::
159132720Skan      _M_transfer_iter(const _Safe_iterator<_Iterator, _Sequence>& __x)
160132720Skan      {
161132720Skan	_Safe_sequence_base* __from = __x._M_sequence;
162132720Skan	if (!__from)
163132720Skan	  return;
164132720Skan
165132720Skan        typedef typename _Sequence::iterator iterator;
166132720Skan        typedef typename _Sequence::const_iterator const_iterator;
167132720Skan
168169691Skan	__gnu_cxx::__scoped_lock sentry(this->_M_get_mutex());
169169691Skan        for (_Safe_iterator_base* __iter = __from->_M_iterators; __iter;)
170169691Skan	  {
171169691Skan	    iterator* __victim = static_cast<iterator*>(__iter);
172169691Skan	    __iter = __iter->_M_next;
173169691Skan	    if (!__victim->_M_singular() && __victim->base() == __x.base())
174169691Skan	      __victim->_M_attach_single(static_cast<_Sequence*>(this));
175169691Skan	  }
176132720Skan
177132720Skan        for (_Safe_iterator_base* __iter2 = __from->_M_const_iterators;
178132720Skan	     __iter2;)
179169691Skan	  {
180169691Skan	    const_iterator* __victim = static_cast<const_iterator*>(__iter2);
181169691Skan	    __iter2 = __iter2->_M_next;
182169691Skan	    if (!__victim->_M_singular() && __victim->base() == __x.base())
183169691Skan	      __victim->_M_attach_single(static_cast<_Sequence*>(this));
184169691Skan	  }
185132720Skan      }
186132720Skan} // namespace __gnu_debug
187132720Skan
188132720Skan#endif
189