1*404b540aSrobert // Safe sequence implementation -*- C++ -*- 2*404b540aSrobert 3*404b540aSrobert // Copyright (C) 2003, 2004, 2005, 2006 4*404b540aSrobert // Free Software Foundation, Inc. 5*404b540aSrobert // 6*404b540aSrobert // This file is part of the GNU ISO C++ Library. This library is free 7*404b540aSrobert // software; you can redistribute it and/or modify it under the 8*404b540aSrobert // terms of the GNU General Public License as published by the 9*404b540aSrobert // Free Software Foundation; either version 2, or (at your option) 10*404b540aSrobert // any later version. 11*404b540aSrobert 12*404b540aSrobert // This library is distributed in the hope that it will be useful, 13*404b540aSrobert // but WITHOUT ANY WARRANTY; without even the implied warranty of 14*404b540aSrobert // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*404b540aSrobert // GNU General Public License for more details. 16*404b540aSrobert 17*404b540aSrobert // You should have received a copy of the GNU General Public License along 18*404b540aSrobert // with this library; see the file COPYING. If not, write to the Free 19*404b540aSrobert // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 20*404b540aSrobert // USA. 21*404b540aSrobert 22*404b540aSrobert // As a special exception, you may use this file as part of a free software 23*404b540aSrobert // library without restriction. Specifically, if other files instantiate 24*404b540aSrobert // templates or use macros or inline functions from this file, or you compile 25*404b540aSrobert // this file and link it with other files to produce an executable, this 26*404b540aSrobert // file does not by itself cause the resulting executable to be covered by 27*404b540aSrobert // the GNU General Public License. This exception does not however 28*404b540aSrobert // invalidate any other reasons why the executable file might be covered by 29*404b540aSrobert // the GNU General Public License. 30*404b540aSrobert 31*404b540aSrobert /** @file debug/safe_sequence.h 32*404b540aSrobert * This file is a GNU debug extension to the Standard C++ Library. 33*404b540aSrobert */ 34*404b540aSrobert 35*404b540aSrobert #ifndef _GLIBCXX_DEBUG_SAFE_SEQUENCE_H 36*404b540aSrobert #define _GLIBCXX_DEBUG_SAFE_SEQUENCE_H 1 37*404b540aSrobert 38*404b540aSrobert #include <debug/debug.h> 39*404b540aSrobert #include <debug/macros.h> 40*404b540aSrobert #include <debug/functions.h> 41*404b540aSrobert #include <debug/safe_base.h> 42*404b540aSrobert 43*404b540aSrobert namespace __gnu_debug 44*404b540aSrobert { 45*404b540aSrobert template<typename _Iterator, typename _Sequence> 46*404b540aSrobert class _Safe_iterator; 47*404b540aSrobert 48*404b540aSrobert /** A simple function object that returns true if the passed-in 49*404b540aSrobert * value is not equal to the stored value. It saves typing over 50*404b540aSrobert * using both bind1st and not_equal. 51*404b540aSrobert */ 52*404b540aSrobert template<typename _Type> 53*404b540aSrobert class _Not_equal_to 54*404b540aSrobert { 55*404b540aSrobert _Type __value; 56*404b540aSrobert 57*404b540aSrobert public: _Not_equal_to(const _Type & __v)58*404b540aSrobert explicit _Not_equal_to(const _Type& __v) : __value(__v) { } 59*404b540aSrobert 60*404b540aSrobert bool operator()61*404b540aSrobert operator()(const _Type& __x) const 62*404b540aSrobert { return __value != __x; } 63*404b540aSrobert }; 64*404b540aSrobert 65*404b540aSrobert /** A function object that returns true when the given random access 66*404b540aSrobert iterator is at least @c n steps away from the given iterator. */ 67*404b540aSrobert template<typename _Iterator> 68*404b540aSrobert class _After_nth_from 69*404b540aSrobert { 70*404b540aSrobert typedef typename std::iterator_traits<_Iterator>::difference_type 71*404b540aSrobert difference_type; 72*404b540aSrobert 73*404b540aSrobert _Iterator _M_base; 74*404b540aSrobert difference_type _M_n; 75*404b540aSrobert 76*404b540aSrobert public: _After_nth_from(const difference_type & __n,const _Iterator & __base)77*404b540aSrobert _After_nth_from(const difference_type& __n, const _Iterator& __base) 78*404b540aSrobert : _M_base(__base), _M_n(__n) { } 79*404b540aSrobert 80*404b540aSrobert bool operator()81*404b540aSrobert operator()(const _Iterator& __x) const 82*404b540aSrobert { return __x - _M_base >= _M_n; } 83*404b540aSrobert }; 84*404b540aSrobert 85*404b540aSrobert /** 86*404b540aSrobert * @brief Base class for constructing a "safe" sequence type that 87*404b540aSrobert * tracks iterators that reference it. 88*404b540aSrobert * 89*404b540aSrobert * The class template %_Safe_sequence simplifies the construction of 90*404b540aSrobert * "safe" sequences that track the iterators that reference the 91*404b540aSrobert * sequence, so that the iterators are notified of changes in the 92*404b540aSrobert * sequence that may affect their operation, e.g., if the container 93*404b540aSrobert * invalidates its iterators or is destructed. This class template 94*404b540aSrobert * may only be used by deriving from it and passing the name of the 95*404b540aSrobert * derived class as its template parameter via the curiously 96*404b540aSrobert * recurring template pattern. The derived class must have @c 97*404b540aSrobert * iterator and @const_iterator types that are instantiations of 98*404b540aSrobert * class template _Safe_iterator for this sequence. Iterators will 99*404b540aSrobert * then be tracked automatically. 100*404b540aSrobert */ 101*404b540aSrobert template<typename _Sequence> 102*404b540aSrobert class _Safe_sequence : public _Safe_sequence_base 103*404b540aSrobert { 104*404b540aSrobert public: 105*404b540aSrobert /** Invalidates all iterators @c x that reference this sequence, 106*404b540aSrobert are not singular, and for which @c pred(x) returns @c 107*404b540aSrobert true. The user of this routine should be careful not to make 108*404b540aSrobert copies of the iterators passed to @p pred, as the copies may 109*404b540aSrobert interfere with the invalidation. */ 110*404b540aSrobert template<typename _Predicate> 111*404b540aSrobert void 112*404b540aSrobert _M_invalidate_if(_Predicate __pred); 113*404b540aSrobert 114*404b540aSrobert /** Transfers all iterators that reference this memory location 115*404b540aSrobert to this sequence from whatever sequence they are attached 116*404b540aSrobert to. */ 117*404b540aSrobert template<typename _Iterator> 118*404b540aSrobert void 119*404b540aSrobert _M_transfer_iter(const _Safe_iterator<_Iterator, _Sequence>& __x); 120*404b540aSrobert }; 121*404b540aSrobert 122*404b540aSrobert template<typename _Sequence> 123*404b540aSrobert template<typename _Predicate> 124*404b540aSrobert void 125*404b540aSrobert _Safe_sequence<_Sequence>:: _M_invalidate_if(_Predicate __pred)126*404b540aSrobert _M_invalidate_if(_Predicate __pred) 127*404b540aSrobert { 128*404b540aSrobert typedef typename _Sequence::iterator iterator; 129*404b540aSrobert typedef typename _Sequence::const_iterator const_iterator; 130*404b540aSrobert 131*404b540aSrobert __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex()); 132*404b540aSrobert for (_Safe_iterator_base* __iter = _M_iterators; __iter;) 133*404b540aSrobert { 134*404b540aSrobert iterator* __victim = static_cast<iterator*>(__iter); 135*404b540aSrobert __iter = __iter->_M_next; 136*404b540aSrobert if (!__victim->_M_singular()) 137*404b540aSrobert { 138*404b540aSrobert if (__pred(__victim->base())) 139*404b540aSrobert __victim->_M_invalidate_single(); 140*404b540aSrobert } 141*404b540aSrobert } 142*404b540aSrobert 143*404b540aSrobert for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;) 144*404b540aSrobert { 145*404b540aSrobert const_iterator* __victim = static_cast<const_iterator*>(__iter2); 146*404b540aSrobert __iter2 = __iter2->_M_next; 147*404b540aSrobert if (!__victim->_M_singular()) 148*404b540aSrobert { 149*404b540aSrobert if (__pred(__victim->base())) 150*404b540aSrobert __victim->_M_invalidate_single(); 151*404b540aSrobert } 152*404b540aSrobert } 153*404b540aSrobert } 154*404b540aSrobert 155*404b540aSrobert template<typename _Sequence> 156*404b540aSrobert template<typename _Iterator> 157*404b540aSrobert void 158*404b540aSrobert _Safe_sequence<_Sequence>:: _M_transfer_iter(const _Safe_iterator<_Iterator,_Sequence> & __x)159*404b540aSrobert _M_transfer_iter(const _Safe_iterator<_Iterator, _Sequence>& __x) 160*404b540aSrobert { 161*404b540aSrobert _Safe_sequence_base* __from = __x._M_sequence; 162*404b540aSrobert if (!__from) 163*404b540aSrobert return; 164*404b540aSrobert 165*404b540aSrobert typedef typename _Sequence::iterator iterator; 166*404b540aSrobert typedef typename _Sequence::const_iterator const_iterator; 167*404b540aSrobert 168*404b540aSrobert __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex()); 169*404b540aSrobert for (_Safe_iterator_base* __iter = __from->_M_iterators; __iter;) 170*404b540aSrobert { 171*404b540aSrobert iterator* __victim = static_cast<iterator*>(__iter); 172*404b540aSrobert __iter = __iter->_M_next; 173*404b540aSrobert if (!__victim->_M_singular() && __victim->base() == __x.base()) 174*404b540aSrobert __victim->_M_attach_single(static_cast<_Sequence*>(this)); 175*404b540aSrobert } 176*404b540aSrobert 177*404b540aSrobert for (_Safe_iterator_base* __iter2 = __from->_M_const_iterators; 178*404b540aSrobert __iter2;) 179*404b540aSrobert { 180*404b540aSrobert const_iterator* __victim = static_cast<const_iterator*>(__iter2); 181*404b540aSrobert __iter2 = __iter2->_M_next; 182*404b540aSrobert if (!__victim->_M_singular() && __victim->base() == __x.base()) 183*404b540aSrobert __victim->_M_attach_single(static_cast<_Sequence*>(this)); 184*404b540aSrobert } 185*404b540aSrobert } 186*404b540aSrobert } // namespace __gnu_debug 187*404b540aSrobert 188*404b540aSrobert #endif 189