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