diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-11-29 13:20:50 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-11-29 13:20:50 +0000 |
commit | e06eeab986ad016975b1380e3cc9556ce382f1d8 (patch) | |
tree | 14f34f69902595b73b37712155769ec5ea51680e /libstdc++-v3 | |
parent | 1852c1a4d9758d3dc7e90e692c891ee62013a47a (diff) | |
download | gcc-e06eeab986ad016975b1380e3cc9556ce382f1d8.tar.gz |
2010-11-29 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 167237
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@167240 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libstdc++-v3')
10 files changed, 614 insertions, 0 deletions
diff --git a/libstdc++-v3/include/debug/safe_sequence.tcc b/libstdc++-v3/include/debug/safe_sequence.tcc new file mode 100644 index 00000000000..bf0295cfd05 --- /dev/null +++ b/libstdc++-v3/include/debug/safe_sequence.tcc @@ -0,0 +1,150 @@ +// Safe sequence implementation -*- C++ -*- + +// Copyright (C) 2010 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/safe_sequence.tcc + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_SAFE_SEQUENCE_TCC +#define _GLIBCXX_DEBUG_SAFE_SEQUENCE_TCC 1 + +namespace __gnu_debug +{ + template<typename _Sequence> + template<typename _Predicate> + void + _Safe_sequence<_Sequence>:: + _M_invalidate_if(_Predicate __pred) + { + typedef typename _Sequence::iterator iterator; + typedef typename _Sequence::const_iterator const_iterator; + + __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex()); + for (_Safe_iterator_base* __iter = _M_iterators; __iter;) + { + iterator* __victim = static_cast<iterator*>(__iter); + __iter = __iter->_M_next; + if (!__victim->_M_singular() && __pred(__victim->base())) + { + __victim->_M_invalidate(); + } + } + + for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;) + { + const_iterator* __victim = static_cast<const_iterator*>(__iter2); + __iter2 = __iter2->_M_next; + if (!__victim->_M_singular() && __pred(__victim->base())) + { + __victim->_M_invalidate(); + } + } + } + + template<typename _Sequence> + template<typename _Predicate> + void + _Safe_sequence<_Sequence>:: + _M_transfer_from_if(_Safe_sequence& __from, _Predicate __pred) + { + typedef typename _Sequence::iterator iterator; + typedef typename _Sequence::const_iterator const_iterator; + + _Safe_iterator_base* __transfered_iterators = 0; + _Safe_iterator_base* __transfered_const_iterators = 0; + _Safe_iterator_base* __last_iterator = 0; + _Safe_iterator_base* __last_const_iterator = 0; + { + // We lock __from first and detach iterator(s) to transfer + __gnu_cxx::__scoped_lock sentry(__from._M_get_mutex()); + + for (_Safe_iterator_base* __iter = __from._M_iterators; __iter;) + { + iterator* __victim = static_cast<iterator*>(__iter); + __iter = __iter->_M_next; + if (!__victim->_M_singular() && __pred(__victim->base())) + { + __victim->_M_detach_single(); + if (__transfered_iterators) + { + __victim->_M_next = __transfered_iterators; + __transfered_iterators->_M_prior = __victim; + } + else + __last_iterator = __victim; + __victim->_M_sequence = this; + __victim->_M_version = this->_M_version; + __transfered_iterators = __victim; + } + } + + for (_Safe_iterator_base* __iter2 = __from._M_const_iterators; + __iter2;) + { + const_iterator* __victim = static_cast<const_iterator*>(__iter2); + __iter2 = __iter2->_M_next; + if (!__victim->_M_singular() && __pred(__victim->base())) + { + __victim->_M_detach_single(); + if (__transfered_const_iterators) + { + __victim->_M_next = __transfered_const_iterators; + __transfered_const_iterators->_M_prior = __victim; + } + else + __last_const_iterator = __victim; + __victim->_M_sequence = this; + __victim->_M_version = this->_M_version; + __transfered_const_iterators = __victim; + } + } + } + + // Now we can lock *this and add the transfered iterators if any + if (__last_iterator || __last_const_iterator) + { + __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex()); + if (__last_iterator) + { + if (this->_M_iterators) + { + this->_M_iterators->_M_prior = __last_iterator; + __last_iterator->_M_next = this->_M_iterators; + } + this->_M_iterators = __transfered_iterators; + } + if (__last_const_iterator) + { + if (this->_M_const_iterators) + { + this->_M_const_iterators->_M_prior = __last_const_iterator; + __last_const_iterator->_M_next = this->_M_const_iterators; + } + this->_M_const_iterators = __transfered_const_iterators; + } + } + } +} // namespace __gnu_debug + +#endif diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/debug/clear.cc b/libstdc++-v3/testsuite/23_containers/forward_list/debug/clear.cc new file mode 100644 index 00000000000..23ea900b87d --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/forward_list/debug/clear.cc @@ -0,0 +1,43 @@ +// { dg-options "-std=gnu++0x" } + +// Copyright (C) 2010 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without Pred the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// Check that iterators ownership is correctly manage on swap. +#include <forward_list> +#include <testsuite_hooks.h> + +void +test01() +{ + bool test __attribute__((unused)) = true; + std::forward_list<int> fl{1, 2, 3}; + + auto before = fl.before_begin(); + auto end = fl.end(); + fl.clear(); + + VERIFY( end == fl.end() ); + VERIFY( before == fl.before_begin() ); +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/debug/move_constructor.cc b/libstdc++-v3/testsuite/23_containers/forward_list/debug/move_constructor.cc new file mode 100644 index 00000000000..4a93666b224 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/forward_list/debug/move_constructor.cc @@ -0,0 +1,43 @@ +// { dg-options "-std=gnu++0x" } + +// Copyright (C) 2010 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without Pred the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// Check that iterators ownership is correctly manage on swap. +#include <forward_list> +#include <testsuite_hooks.h> + +void +test01() +{ + bool test __attribute__((unused)) = true; + std::forward_list<int> fl1{1, 3, 5}; + + auto flit = fl1.before_begin(); + std::forward_list<int> fl2(std::move(fl1)); + +#if !_GLIBCXX_DEBUG + VERIFY( flit == fl1.before_begin() ); +#endif +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/debug/splice_after.cc b/libstdc++-v3/testsuite/23_containers/forward_list/debug/splice_after.cc new file mode 100644 index 00000000000..60297551dcd --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/forward_list/debug/splice_after.cc @@ -0,0 +1,44 @@ +// { dg-options "-std=gnu++0x" } + +// Copyright (C) 2010 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without Pred the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// Check that iterators ownership is correctly manage on swap. +#include <forward_list> +#include <testsuite_hooks.h> + +void +test01() +{ + bool test __attribute__((unused)) = true; + std::forward_list<int> fl1{1, 2, 3}; + std::forward_list<int> fl2{4, 5, 6}; + + auto before = fl1.before_begin(); + auto end = fl1.end(); + fl2.splice_after(fl2.before_begin(), std::move(fl1)); + + VERIFY( before == fl1.before_begin() ); + VERIFY( end == fl1.end() ); +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/debug/splice_after1.cc b/libstdc++-v3/testsuite/23_containers/forward_list/debug/splice_after1.cc new file mode 100644 index 00000000000..3ee7f689aeb --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/forward_list/debug/splice_after1.cc @@ -0,0 +1,36 @@ +// { dg-options "-std=gnu++0x" } +// { dg-require-debug-mode "" } +// { dg-do run { xfail *-*-* } } + +// Copyright (C) 2010 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without Pred the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <forward_list> + +void +test01() +{ + std::forward_list<int> fl1{1, 2, 3}; + fl1.splice_after(fl1.begin(), std::move(fl1)); +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/debug/splice_after2.cc b/libstdc++-v3/testsuite/23_containers/forward_list/debug/splice_after2.cc new file mode 100644 index 00000000000..6a7fcfb22c2 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/forward_list/debug/splice_after2.cc @@ -0,0 +1,38 @@ +// { dg-options "-std=gnu++0x" } +// { dg-require-debug-mode "" } +// { dg-do run { xfail *-*-* } } + +// Copyright (C) 2010 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without Pred the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <forward_list> + +void +test01() +{ + std::forward_list<int> fl1{1, 2, 3}; + std::forward_list<int> fl2{1, 2, 3}; + + fl1.splice_after(fl1.before_begin(), std::move(fl2), fl1.begin()); +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/debug/splice_after3.cc b/libstdc++-v3/testsuite/23_containers/forward_list/debug/splice_after3.cc new file mode 100644 index 00000000000..55e50dc0511 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/forward_list/debug/splice_after3.cc @@ -0,0 +1,38 @@ +// { dg-options "-std=gnu++0x" } +// { dg-require-debug-mode "" } +// { dg-do run { xfail *-*-* } } + +// Copyright (C) 2010 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without Pred the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <forward_list> + +void +test01() +{ + std::forward_list<int> fl1{1, 2, 3}; + std::forward_list<int> fl2{1, 2, 3}; + + fl1.splice_after(fl1.before_begin(), std::move(fl2), fl2.end()); +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/debug/splice_after4.cc b/libstdc++-v3/testsuite/23_containers/forward_list/debug/splice_after4.cc new file mode 100644 index 00000000000..4c161906e0a --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/forward_list/debug/splice_after4.cc @@ -0,0 +1,39 @@ +// { dg-options "-std=gnu++0x" } +// { dg-require-debug-mode "" } +// { dg-do run { xfail *-*-* } } + +// Copyright (C) 2010 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without Pred the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <forward_list> + +void +test01() +{ + std::forward_list<int> fl1{1, 2, 3}; + std::forward_list<int> fl2{1, 2, 3}; + + fl1.splice_after(fl1.before_begin(), + std::move(fl2), ++(++fl2.begin()), ++fl2.begin()); +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/debug/swap.cc b/libstdc++-v3/testsuite/23_containers/forward_list/debug/swap.cc new file mode 100644 index 00000000000..0105791bedc --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/forward_list/debug/swap.cc @@ -0,0 +1,83 @@ +// { dg-options "-std=gnu++0x" } + +// Copyright (C) 2010 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without Pred the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// Check that iterators ownership is correctly manage on swap. +#include <vector> +#include <forward_list> +#include <iostream> +#include <testsuite_hooks.h> + +void +test01() +{ + bool test __attribute__((unused)) = true; + std::forward_list<int> fl1{1, 3, 5}; + std::forward_list<int> fl2{2, 4, 6}; + + std::vector<std::forward_list<int>::iterator> fl1_its; + fl1_its.push_back(fl1.before_begin()); + for (std::forward_list<int>::iterator it = fl1.begin(); + it != fl1.end(); ++it) + { + fl1_its.push_back(it); + } + fl1_its.push_back(fl1.end()); + + std::vector<std::forward_list<int>::iterator> fl2_its; + fl2_its.push_back(fl2.before_begin()); + for (std::forward_list<int>::iterator it = fl2.begin(); + it != fl2.end(); ++it) + { + fl2_its.push_back(it); + } + fl2_its.push_back(fl2.end()); + + fl1.swap(fl2); + + auto fit = fl1.before_begin(); + // before-begin iterator is not transfered: + // TODO: Validate with LWG group how before begin should be + // treated. +#if !_GLIBCXX_DEBUG + VERIFY( fit == fl1_its[0] ); +#endif + // All others are, even paste-the-end one: + for (size_t i = 1; i != fl2_its.size(); ++i) + { + VERIFY( ++fit == fl2_its[i] ); + } + + fit = fl2.before_begin(); + // TODO: Validate with LWG group how before begin should be + // treated. +#if !_GLIBCXX_DEBUG + VERIFY( fit == fl2_its[0] ); +#endif + for (size_t i = 1; i != fl1_its.size(); ++i) + { + VERIFY( ++fit == fl1_its[i] ); + } +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/debug/multithreaded_swap.cc b/libstdc++-v3/testsuite/23_containers/vector/debug/multithreaded_swap.cc new file mode 100644 index 00000000000..b2a50aa21c8 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/debug/multithreaded_swap.cc @@ -0,0 +1,100 @@ +// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* alpha*-*-osf* mips-sgi-irix6* } } +// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* alpha*-*-osf* mips-sgi-irix6* } } +// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } } +// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } } +// { dg-require-cstdint "" } +// { dg-require-gthreads "" } +// { dg-require-debug-mode "" } +// Copyright (C) 2010 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. +// + +// This test check for potential deadlock when swaping sequences in debug +// mode as it requires acquiring 2 locks at the same time. + +#include <vector> +#include <thread> +#include <functional> +#include <testsuite_hooks.h> + +// The following function mimic the one in src/debug.cc to associate a mutex +// to a given safe sequence instance. +size_t +get_index(std::vector<int>& v) +{ + const size_t mask = 0xf; + // We have to check the address of the internal safe sequence that starts + // after the normal vector memory footprint that is to say a 3 pointers + // offset: + void* __address = reinterpret_cast<char*>(&v) + 3 * sizeof(void*); + return std::_Hash_impl::hash(__address) & mask; +} + +void test01() +{ + using namespace std; + bool test __attribute__((unused)) = true; + vector<int> v1, v2; + vector<shared_ptr<vector<int> > > vs; + vector<int> *pv3 = 0, *pv4 = 0; + const int nb_attempts = 100; + for (int i = 0; i != nb_attempts; ++i) + { + vs.push_back(shared_ptr<vector<int> >(new vector<int>())); + if (!pv3) + { + if (get_index(*vs.back()) == get_index(v1)) + pv3 = vs.back().get(); + } + else if (!pv4) + { + if (get_index(*vs.back()) == get_index(v2)) + { + pv4 = vs.back().get(); + break; + } + } + } + + if (!pv3 || !pv4) + // Maybe an other time... + return; + + vector<int> &v3 = *pv3, &v4 = *pv4; + + // v1 and v3 shares the same mutex instance, like v2 and v4 + // thread t1 lock v1 and v2 + thread t1([&v1, &v2]() + { + for (int i = 0; i != 1000; ++i) + v1.swap(v2); + }); + // thread t2 lock v4 and v3 + thread t2([&v3, &v4]() + { + for (int i = 0; i != 1000; ++i) + v4.swap(v3); + }); + t2.join(); + t1.join(); +} + +int main() +{ + test01(); + return 0; +} |