1 //===----------------------------------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // UNSUPPORTED: libcpp-has-no-threads
10 // UNSUPPORTED: c++03, c++11
11 
12 // shared_timed_mutex was introduced in macosx10.12
13 // UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11}}
14 
15 // <shared_mutex>
16 
17 // class shared_timed_mutex;
18 
19 // void lock_shared();
20 
21 #include <thread>
22 
23 #include <atomic>
24 #include <cassert>
25 #include <cstdlib>
26 #include <shared_mutex>
27 #include <vector>
28 
29 #include "make_test_thread.h"
30 #include "test_macros.h"
31 
32 std::shared_timed_mutex m;
33 
34 typedef std::chrono::system_clock Clock;
35 typedef Clock::time_point time_point;
36 typedef Clock::duration duration;
37 typedef std::chrono::milliseconds ms;
38 typedef std::chrono::nanoseconds ns;
39 
40 std::atomic<unsigned> countDown;
41 time_point readerStart; // Protected by the above mutex 'm'
42 time_point writerStart; // Protected by the above mutex 'm'
43 
44 ms WaitTime = ms(250);
45 
46 void readerMustWait() {
47   --countDown;
48   m.lock_shared();
49   time_point t1 = Clock::now();
50   time_point t0 = readerStart;
51   m.unlock_shared();
52   assert(t0.time_since_epoch() > ms(0));
53   assert(t1 - t0 >= WaitTime);
54 }
55 
56 void reader() {
57   --countDown;
58   m.lock_shared();
59   m.unlock_shared();
60 }
61 
62 void writerMustWait() {
63   --countDown;
64   m.lock();
65   time_point t1 = Clock::now();
66   time_point t0 = writerStart;
67   m.unlock();
68   assert(t0.time_since_epoch() > ms(0));
69   assert(t1 - t0 >= WaitTime);
70 }
71 
72 int main(int, char**)
73 {
74   int threads = 5;
75 
76   countDown.store(threads);
77   m.lock();
78   std::vector<std::thread> v;
79   for (int i = 0; i < threads; ++i)
80     v.push_back(support::make_test_thread(readerMustWait));
81   while (countDown > 0)
82     std::this_thread::yield();
83   readerStart = Clock::now();
84   std::this_thread::sleep_for(WaitTime);
85   m.unlock();
86   for (auto& t : v)
87     t.join();
88 
89   countDown.store(threads + 1);
90   m.lock_shared();
91   for (auto& t : v)
92     t = support::make_test_thread(reader);
93   std::thread q = support::make_test_thread(writerMustWait);
94   while (countDown > 0)
95     std::this_thread::yield();
96   writerStart = Clock::now();
97   std::this_thread::sleep_for(WaitTime);
98   m.unlock_shared();
99   for (auto& t : v)
100     t.join();
101   q.join();
102 
103   return 0;
104 }
105