summaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2010-11-29 13:20:50 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2010-11-29 13:20:50 +0000
commite06eeab986ad016975b1380e3cc9556ce382f1d8 (patch)
tree14f34f69902595b73b37712155769ec5ea51680e /libstdc++-v3
parent1852c1a4d9758d3dc7e90e692c891ee62013a47a (diff)
downloadgcc-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')
-rw-r--r--libstdc++-v3/include/debug/safe_sequence.tcc150
-rw-r--r--libstdc++-v3/testsuite/23_containers/forward_list/debug/clear.cc43
-rw-r--r--libstdc++-v3/testsuite/23_containers/forward_list/debug/move_constructor.cc43
-rw-r--r--libstdc++-v3/testsuite/23_containers/forward_list/debug/splice_after.cc44
-rw-r--r--libstdc++-v3/testsuite/23_containers/forward_list/debug/splice_after1.cc36
-rw-r--r--libstdc++-v3/testsuite/23_containers/forward_list/debug/splice_after2.cc38
-rw-r--r--libstdc++-v3/testsuite/23_containers/forward_list/debug/splice_after3.cc38
-rw-r--r--libstdc++-v3/testsuite/23_containers/forward_list/debug/splice_after4.cc39
-rw-r--r--libstdc++-v3/testsuite/23_containers/forward_list/debug/swap.cc83
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/debug/multithreaded_swap.cc100
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;
+}