1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: no-threads
10 // UNSUPPORTED: c++03, c++11
14 // class shared_timed_mutex;
16 // void lock_shared();
18 #include <shared_mutex>
25 #include "make_test_thread.h"
27 int main(int, char**) {
28 // Lock-shared a mutex that is not locked yet. This should succeed.
30 std::shared_timed_mutex m
;
31 std::vector
<std::thread
> threads
;
32 for (int i
= 0; i
!= 5; ++i
) {
33 threads
.push_back(support::make_test_thread([&] {
39 for (auto& t
: threads
)
43 // Lock-shared a mutex that is already exclusively locked. This should block until it is unlocked.
45 std::atomic
<int> ready(0);
46 std::shared_timed_mutex m
;
48 std::atomic
<bool> is_locked_from_main(true);
50 std::vector
<std::thread
> threads
;
51 for (int i
= 0; i
!= 5; ++i
) {
52 threads
.push_back(support::make_test_thread([&] {
55 /* wait until all threads have been created */;
58 assert(!is_locked_from_main
);
64 /* wait until all threads have been created */;
66 // We would rather signal this after we unlock, but that would create a race condition.
67 // We instead signal it before we unlock, which means that it's technically possible for
68 // the thread to take the lock while we're still holding it and for the test to still pass.
69 is_locked_from_main
= false;
72 for (auto& t
: threads
)
76 // Lock-shared a mutex that is already lock-shared. This should succeed.
78 std::atomic
<int> ready(0);
79 std::shared_timed_mutex m
;
82 std::vector
<std::thread
> threads
;
83 for (int i
= 0; i
!= 5; ++i
) {
84 threads
.push_back(support::make_test_thread([&] {
87 /* wait until all threads have been created */;
95 /* wait until all threads have been created */;
99 for (auto& t
: threads
)
103 // Create several threads that all acquire-shared the same mutex and make sure that each
104 // thread successfully acquires-shared the mutex.
106 // We record how many other threads were holding the mutex when it was acquired, which allows
107 // us to know whether the test was somewhat effective at causing multiple threads to lock at
110 std::shared_timed_mutex mutex
;
111 std::vector
<std::thread
> threads
;
112 constexpr int n_threads
= 5;
113 std::atomic
<int> holders(0);
114 int concurrent_holders
[n_threads
] = {};
115 std::atomic
<bool> ready(false);
117 for (int i
= 0; i
!= n_threads
; ++i
) {
118 threads
.push_back(support::make_test_thread([&, i
] {
124 concurrent_holders
[i
] = holders
;
126 mutex
.unlock_shared();
131 ready
= true; // let the threads actually start shared-acquiring the mutex
132 for (auto& t
: threads
)
135 // We can't guarantee that we'll ever have more than 1 concurrent holder so that's what
136 // we assert, however in principle we should often trigger more than 1 concurrent holder.
137 int max_concurrent_holders
= *std::max_element(std::begin(concurrent_holders
), std::end(concurrent_holders
));
138 assert(max_concurrent_holders
>= 1);