// Debugging mode support code -*- C++ -*-
-// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-// Free Software Foundation, Inc.
+// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+// 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
#include <debug/debug.h>
#include <debug/safe_sequence.h>
+#include <debug/safe_unordered_sequence.h>
#include <debug/safe_iterator.h>
+#include <debug/safe_local_iterator.h>
#include <algorithm>
#include <cassert>
#include <cstring>
}
void
- swap_seq(__gnu_debug::_Safe_sequence_base& __lhs,
- __gnu_debug::_Safe_sequence_base& __rhs)
+ swap_its(__gnu_debug::_Safe_sequence_base& __lhs,
+ __gnu_debug::_Safe_iterator_base*& __lhs_its,
+ __gnu_debug::_Safe_sequence_base& __rhs,
+ __gnu_debug::_Safe_iterator_base*& __rhs_its)
{
- swap(__lhs._M_iterators, __rhs._M_iterators);
- swap(__lhs._M_const_iterators, __rhs._M_const_iterators);
- swap(__lhs._M_version, __rhs._M_version);
+ swap(__lhs_its, __rhs_its);
__gnu_debug::_Safe_iterator_base* __iter;
- for (__iter = __rhs._M_iterators; __iter; __iter = __iter->_M_next)
- __iter->_M_sequence = &__rhs;
- for (__iter = __lhs._M_iterators; __iter; __iter = __iter->_M_next)
- __iter->_M_sequence = &__lhs;
- for (__iter = __rhs._M_const_iterators; __iter; __iter = __iter->_M_next)
+ for (__iter = __rhs_its; __iter; __iter = __iter->_M_next)
__iter->_M_sequence = &__rhs;
- for (__iter = __lhs._M_const_iterators; __iter; __iter = __iter->_M_next)
+ for (__iter = __lhs_its; __iter; __iter = __iter->_M_next)
__iter->_M_sequence = &__lhs;
}
+
+ void
+ swap_seq(__gnu_debug::_Safe_sequence_base& __lhs,
+ __gnu_debug::_Safe_sequence_base& __rhs)
+ {
+ swap(__lhs._M_version, __rhs._M_version);
+ swap_its(__lhs, __lhs._M_iterators,
+ __rhs, __rhs._M_iterators);
+ swap_its(__lhs, __lhs._M_const_iterators,
+ __rhs, __rhs._M_const_iterators);
+ }
+
+ void
+ swap_useq(__gnu_debug::_Safe_unordered_sequence_base& __lhs,
+ __gnu_debug::_Safe_unordered_sequence_base& __rhs)
+ {
+ swap_seq(__lhs, __rhs);
+ swap_its(__lhs, __lhs._M_local_iterators,
+ __rhs, __rhs._M_local_iterators);
+ swap_its(__lhs, __lhs._M_const_local_iterators,
+ __rhs, __rhs._M_const_local_iterators);
+ }
+
+ void
+ detach_all(__gnu_debug::_Safe_iterator_base* __iter)
+ {
+ for (; __iter;)
+ {
+ __gnu_debug::_Safe_iterator_base* __old = __iter;
+ __iter = __iter->_M_next;
+ __old->_M_reset();
+ }
+ }
} // anonymous namespace
namespace __gnu_debug
{
const char* _S_debug_messages[] =
{
+ // General Checks
"function requires a valid iterator range [%1.name;, %2.name;)",
"attempt to insert into container with a singular iterator",
"attempt to insert into container with an iterator"
"elements in iterator range [%1.name;, %2.name;) do not form a heap",
"elements in iterator range [%1.name;, %2.name;)"
" do not form a heap with respect to the predicate %3;",
+ // std::bitset checks
"attempt to write through a singular bitset reference",
"attempt to read from a singular bitset reference",
"attempt to flip a singular bitset reference",
+ // std::list checks
"attempt to splice a list into itself",
"attempt to splice lists with inequal allocators",
"attempt to splice elements referenced by a %1.state; iterator",
"attempt to splice an iterator from a different container",
"splice destination %1.name;"
" occurs within source range [%2.name;, %3.name;)",
+ // iterator checks
"attempt to initialize an iterator that will immediately become singular",
"attempt to copy-construct an iterator from a singular iterator",
"attempt to construct a constant iterator"
" iterator to a %2.state; iterator",
"attempt to compute the different between two iterators"
" from different sequences",
+ // istream_iterator
"attempt to dereference an end-of-stream istream_iterator",
"attempt to increment an end-of-stream istream_iterator",
+ // ostream_iterator
"attempt to output via an ostream_iterator with no associated stream",
+ // istreambuf_iterator
"attempt to dereference an end-of-stream istreambuf_iterator"
" (this is a GNU extension)",
"attempt to increment an end-of-stream istreambuf_iterator",
+ // std::forward_list
"attempt to insert into container after an end iterator",
"attempt to erase from container after a %2.state; iterator not followed"
" by a dereferenceable one",
"function requires a valid iterator range (%2.name;, %3.name;)"
- ", \"%2.name;\" shall be before and not equal to \"%3.name;\""
+ ", \"%2.name;\" shall be before and not equal to \"%3.name;\"",
+ // std::unordered_sequence::local_iterator
+ "attempt to compare local iterators from different unordered sequence"
+ " buckets"
};
void
_M_detach_all()
{
__gnu_cxx::__scoped_lock sentry(_M_get_mutex());
- for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
- {
- _Safe_iterator_base* __old = __iter;
- __iter = __iter->_M_next;
- __old->_M_reset();
- }
+ detach_all(_M_iterators);
_M_iterators = 0;
- for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
- {
- _Safe_iterator_base* __old = __iter2;
- __iter2 = __iter2->_M_next;
- __old->_M_reset();
- }
+ detach_all(_M_const_iterators);
_M_const_iterators = 0;
}
_M_detach()
{
if (_M_sequence)
- {
- _M_sequence->_M_detach(this);
- }
+ _M_sequence->_M_detach(this);
_M_reset();
}
_M_detach_single() throw ()
{
if (_M_sequence)
- {
- _M_sequence->_M_detach_single(this);
- }
+ _M_sequence->_M_detach_single(this);
_M_reset();
}
_M_get_mutex() throw ()
{ return get_safe_base_mutex(_M_sequence); }
+ _Safe_unordered_sequence_base*
+ _Safe_local_iterator_base::
+ _M_get_sequence() const _GLIBCXX_NOEXCEPT
+ { return static_cast<_Safe_unordered_sequence_base*>(_M_sequence); }
+
+ void
+ _Safe_local_iterator_base::
+ _M_attach(_Safe_sequence_base* __seq, bool __constant)
+ {
+ _M_detach();
+
+ // Attach to the new sequence (if there is one)
+ if (__seq)
+ {
+ _M_sequence = __seq;
+ _M_version = _M_sequence->_M_version;
+ _M_get_sequence()->_M_attach_local(this, __constant);
+ }
+ }
+
+ void
+ _Safe_local_iterator_base::
+ _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw ()
+ {
+ _M_detach_single();
+
+ // Attach to the new sequence (if there is one)
+ if (__seq)
+ {
+ _M_sequence = __seq;
+ _M_version = _M_sequence->_M_version;
+ _M_get_sequence()->_M_attach_local_single(this, __constant);
+ }
+ }
+
+ void
+ _Safe_local_iterator_base::
+ _M_detach()
+ {
+ if (_M_sequence)
+ _M_get_sequence()->_M_detach_local(this);
+
+ _M_reset();
+ }
+
+ void
+ _Safe_local_iterator_base::
+ _M_detach_single() throw ()
+ {
+ if (_M_sequence)
+ _M_get_sequence()->_M_detach_local_single(this);
+
+ _M_reset();
+ }
+
+ void
+ _Safe_unordered_sequence_base::
+ _M_detach_all()
+ {
+ __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
+ detach_all(_M_iterators);
+ _M_iterators = 0;
+
+ detach_all(_M_const_iterators);
+ _M_const_iterators = 0;
+
+ detach_all(_M_local_iterators);
+ _M_local_iterators = 0;
+
+ detach_all(_M_const_local_iterators);
+ _M_const_local_iterators = 0;
+ }
+
+ void
+ _Safe_unordered_sequence_base::
+ _M_swap(_Safe_unordered_sequence_base& __x)
+ {
+ // We need to lock both sequences to swap
+ using namespace __gnu_cxx;
+ __mutex *__this_mutex = &_M_get_mutex();
+ __mutex *__x_mutex = &__x._M_get_mutex();
+ if (__this_mutex == __x_mutex)
+ {
+ __scoped_lock __lock(*__this_mutex);
+ swap_useq(*this, __x);
+ }
+ else
+ {
+ __scoped_lock __l1(__this_mutex < __x_mutex
+ ? *__this_mutex : *__x_mutex);
+ __scoped_lock __l2(__this_mutex < __x_mutex
+ ? *__x_mutex : *__this_mutex);
+ swap_useq(*this, __x);
+ }
+ }
+
+ void
+ _Safe_unordered_sequence_base::
+ _M_attach_local(_Safe_iterator_base* __it, bool __constant)
+ {
+ __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
+ _M_attach_local_single(__it, __constant);
+ }
+
+ void
+ _Safe_unordered_sequence_base::
+ _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) throw ()
+ {
+ _Safe_iterator_base*& __its =
+ __constant ? _M_const_local_iterators : _M_local_iterators;
+ __it->_M_next = __its;
+ if (__it->_M_next)
+ __it->_M_next->_M_prior = __it;
+ __its = __it;
+ }
+
+ void
+ _Safe_unordered_sequence_base::
+ _M_detach_local(_Safe_iterator_base* __it)
+ {
+ // Remove __it from this sequence's list
+ __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
+ _M_detach_local_single(__it);
+ }
+
+ void
+ _Safe_unordered_sequence_base::
+ _M_detach_local_single(_Safe_iterator_base* __it) throw ()
+ {
+ // Remove __it from this sequence's list
+ __it->_M_unlink();
+ if (_M_const_local_iterators == __it)
+ _M_const_local_iterators = __it->_M_next;
+ if (_M_local_iterators == __it)
+ _M_local_iterators = __it->_M_next;
+ }
+
void
_Error_formatter::_Parameter::
_M_print_field(const _Error_formatter* __formatter, const char* __name) const