]>
Commit | Line | Data |
---|---|---|
d1236680 RO |
1 | // { dg-do run } |
2 | // { dg-options "-pthread" } | |
71c54f8e | 3 | // { dg-require-effective-target c++11 } |
d1236680 | 4 | // { dg-require-effective-target pthread } |
afe96d41 FD |
5 | // { dg-require-gthreads "" } |
6 | // { dg-require-debug-mode "" } | |
8d9254fc | 7 | // Copyright (C) 2010-2020 Free Software Foundation, Inc. |
afe96d41 FD |
8 | // |
9 | // This file is part of the GNU ISO C++ Library. This library is free | |
10 | // software; you can redistribute it and/or modify it under the | |
11 | // terms of the GNU General Public License as published by the | |
12 | // Free Software Foundation; either version 3, or (at your option) | |
13 | // any later version. | |
14 | // | |
15 | // This library is distributed in the hope that it will be useful, | |
16 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | // GNU General Public License for more details. | |
19 | // | |
20 | // You should have received a copy of the GNU General Public License along | |
21 | // with this library; see the file COPYING3. If not see | |
22 | // <http://www.gnu.org/licenses/>. | |
23 | // | |
24 | ||
25 | // This test check for potential deadlock when swaping sequences in debug | |
26 | // mode as it requires acquiring 2 locks at the same time. | |
27 | ||
28 | #include <vector> | |
29 | #include <thread> | |
30 | #include <functional> | |
31 | #include <testsuite_hooks.h> | |
32 | ||
33 | // The following function mimic the one in src/debug.cc to associate a mutex | |
34 | // to a given safe sequence instance. | |
35 | size_t | |
36 | get_index(std::vector<int>& v) | |
37 | { | |
38 | const size_t mask = 0xf; | |
39 | // We have to check the address of the internal safe sequence that starts | |
40 | // after the normal vector memory footprint that is to say a 3 pointers | |
41 | // offset: | |
42 | void* __address = reinterpret_cast<char*>(&v) + 3 * sizeof(void*); | |
43 | return std::_Hash_impl::hash(__address) & mask; | |
44 | } | |
45 | ||
46 | void test01() | |
47 | { | |
48 | using namespace std; | |
afe96d41 FD |
49 | vector<int> v1, v2; |
50 | vector<shared_ptr<vector<int> > > vs; | |
51 | vector<int> *pv3 = 0, *pv4 = 0; | |
52 | const int nb_attempts = 100; | |
53 | for (int i = 0; i != nb_attempts; ++i) | |
54 | { | |
55 | vs.push_back(shared_ptr<vector<int> >(new vector<int>())); | |
56 | if (!pv3) | |
57 | { | |
58 | if (get_index(*vs.back()) == get_index(v1)) | |
59 | pv3 = vs.back().get(); | |
60 | } | |
61 | else if (!pv4) | |
62 | { | |
63 | if (get_index(*vs.back()) == get_index(v2)) | |
64 | { | |
65 | pv4 = vs.back().get(); | |
66 | break; | |
67 | } | |
68 | } | |
69 | } | |
70 | ||
71 | if (!pv3 || !pv4) | |
72 | // Maybe an other time... | |
73 | return; | |
74 | ||
75 | vector<int> &v3 = *pv3, &v4 = *pv4; | |
76 | ||
77 | // v1 and v3 shares the same mutex instance, like v2 and v4 | |
78 | // thread t1 lock v1 and v2 | |
79 | thread t1([&v1, &v2]() | |
80 | { | |
81 | for (int i = 0; i != 1000; ++i) | |
82 | v1.swap(v2); | |
83 | }); | |
84 | // thread t2 lock v4 and v3 | |
85 | thread t2([&v3, &v4]() | |
86 | { | |
87 | for (int i = 0; i != 1000; ++i) | |
88 | v4.swap(v3); | |
89 | }); | |
90 | t2.join(); | |
91 | t1.join(); | |
92 | } | |
93 | ||
94 | int main() | |
95 | { | |
96 | test01(); | |
97 | return 0; | |
98 | } |