libstdc++
safe_sequence.tcc
Go to the documentation of this file.
00001 // Safe sequence implementation  -*- C++ -*-
00002 
00003 // Copyright (C) 2010 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 3, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 /** @file debug/safe_sequence.tcc
00026  *  This file is a GNU debug extension to the Standard C++ Library.
00027  */
00028 
00029 #ifndef _GLIBCXX_DEBUG_SAFE_SEQUENCE_TCC
00030 #define _GLIBCXX_DEBUG_SAFE_SEQUENCE_TCC 1
00031 
00032 namespace __gnu_debug
00033 {
00034   template<typename _Sequence>
00035     template<typename _Predicate>
00036       void
00037       _Safe_sequence<_Sequence>::
00038       _M_invalidate_if(_Predicate __pred)
00039       {
00040         typedef typename _Sequence::iterator iterator;
00041         typedef typename _Sequence::const_iterator const_iterator;
00042 
00043     __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex());
00044         for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
00045       {
00046         iterator* __victim = static_cast<iterator*>(__iter);
00047         __iter = __iter->_M_next;
00048         if (!__victim->_M_singular() && __pred(__victim->base()))
00049           {
00050         __victim->_M_invalidate();
00051           }
00052       }
00053 
00054         for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
00055       {
00056         const_iterator* __victim = static_cast<const_iterator*>(__iter2);
00057         __iter2 = __iter2->_M_next;
00058         if (!__victim->_M_singular() && __pred(__victim->base()))
00059           {
00060         __victim->_M_invalidate();
00061           }
00062       }
00063       }
00064 
00065   template<typename _Sequence>
00066     template<typename _Predicate>
00067       void
00068       _Safe_sequence<_Sequence>::
00069       _M_transfer_from_if(_Safe_sequence& __from, _Predicate __pred)
00070       {
00071         typedef typename _Sequence::iterator iterator;
00072         typedef typename _Sequence::const_iterator const_iterator;
00073 
00074     _Safe_iterator_base* __transfered_iterators = 0;
00075     _Safe_iterator_base* __transfered_const_iterators = 0;
00076     _Safe_iterator_base* __last_iterator = 0;
00077     _Safe_iterator_base* __last_const_iterator = 0;
00078     {
00079       // We lock __from first and detach iterator(s) to transfer
00080       __gnu_cxx::__scoped_lock sentry(__from._M_get_mutex());
00081 
00082           for (_Safe_iterator_base* __iter = __from._M_iterators; __iter;)
00083         {
00084           iterator* __victim = static_cast<iterator*>(__iter);
00085           __iter = __iter->_M_next;
00086           if (!__victim->_M_singular() && __pred(__victim->base()))
00087         {
00088           __victim->_M_detach_single();
00089           if (__transfered_iterators)
00090             {
00091               __victim->_M_next = __transfered_iterators;
00092               __transfered_iterators->_M_prior = __victim;
00093             }
00094           else
00095             __last_iterator = __victim;
00096           __victim->_M_sequence = this;
00097           __victim->_M_version = this->_M_version;
00098           __transfered_iterators = __victim;
00099         }
00100         }
00101 
00102       for (_Safe_iterator_base* __iter2 = __from._M_const_iterators;
00103          __iter2;)
00104         {
00105           const_iterator* __victim = static_cast<const_iterator*>(__iter2);
00106           __iter2 = __iter2->_M_next;
00107           if (!__victim->_M_singular() && __pred(__victim->base()))
00108         {
00109           __victim->_M_detach_single();
00110           if (__transfered_const_iterators)
00111             {
00112               __victim->_M_next = __transfered_const_iterators;
00113               __transfered_const_iterators->_M_prior = __victim;
00114             }
00115           else
00116             __last_const_iterator = __victim;
00117           __victim->_M_sequence = this;
00118           __victim->_M_version = this->_M_version;
00119           __transfered_const_iterators = __victim;
00120         }
00121         }
00122     }
00123 
00124     // Now we can lock *this and add the transfered iterators if any
00125     if (__last_iterator || __last_const_iterator)
00126       {
00127         __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex());
00128         if (__last_iterator)
00129           {
00130         if (this->_M_iterators)
00131           {
00132             this->_M_iterators->_M_prior = __last_iterator;
00133             __last_iterator->_M_next = this->_M_iterators;
00134           }
00135         this->_M_iterators = __transfered_iterators;
00136           }
00137         if (__last_const_iterator)
00138           {
00139         if (this->_M_const_iterators)
00140           {
00141             this->_M_const_iterators->_M_prior = __last_const_iterator;
00142             __last_const_iterator->_M_next = this->_M_const_iterators;
00143           }
00144         this->_M_const_iterators = __transfered_const_iterators;
00145           }
00146       }
00147       }
00148 } // namespace __gnu_debug
00149 
00150 #endif