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: no-threads
10 // UNSUPPORTED: c++03, c++11
11 
12 // ALLOW_RETRIES: 2
13 
14 // shared_timed_mutex was introduced in macosx10.12
15 // UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11}}
16 
17 // <shared_mutex>
18 
19 // class shared_timed_mutex;
20 
21 // template <class Clock, class Duration>
22 //     bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time);
23 
24 #include <thread>
25 
26 #include <atomic>
27 #include <cassert>
28 #include <cstdlib>
29 #include <shared_mutex>
30 #include <vector>
31 
32 #include "make_test_thread.h"
33 #include "test_macros.h"
34 
35 std::shared_timed_mutex m;
36 
37 typedef std::chrono::steady_clock Clock;
38 typedef Clock::time_point time_point;
39 typedef Clock::duration duration;
40 typedef std::chrono::milliseconds ms;
41 typedef std::chrono::nanoseconds ns;
42 
43 ms SuccessWaitTime = ms(5000); // Some machines are busy or slow or both
44 ms FailureWaitTime = ms(50);
45 
46 // On busy or slow machines, there can be a significant delay between thread
47 // creation and thread start, so we use an atomic variable to signal that the
48 // thread is actually executing.
49 static std::atomic<unsigned> countDown;
50 
f1()51 void f1()
52 {
53   --countDown;
54   time_point t0 = Clock::now();
55   assert(m.try_lock_shared_until(Clock::now() + SuccessWaitTime) == true);
56   time_point t1 = Clock::now();
57   m.unlock_shared();
58   assert(t1 - t0 <= SuccessWaitTime);
59 }
60 
f2()61 void f2()
62 {
63   time_point t0 = Clock::now();
64   assert(m.try_lock_shared_until(Clock::now() + FailureWaitTime) == false);
65   assert(Clock::now() - t0 >= FailureWaitTime);
66 }
67 
main(int,char **)68 int main(int, char**)
69 {
70   int threads = 5;
71   {
72     countDown.store(threads);
73     m.lock();
74     std::vector<std::thread> v;
75     for (int i = 0; i < threads; ++i)
76       v.push_back(support::make_test_thread(f1));
77     while (countDown > 0)
78       std::this_thread::yield();
79     m.unlock();
80     for (auto& t : v)
81       t.join();
82   }
83   {
84     m.lock();
85     std::vector<std::thread> v;
86     for (int i = 0; i < threads; ++i)
87       v.push_back(support::make_test_thread(f2));
88     for (auto& t : v)
89       t.join();
90     m.unlock();
91   }
92 
93   return 0;
94 }
95