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++98, c++03, c++11
11 
12 // <shared_mutex>
13 
14 // template <class Mutex> class shared_lock;
15 
16 // void lock();
17 
18 #include <shared_mutex>
19 #include <thread>
20 #include <vector>
21 #include <cstdlib>
22 #include <cassert>
23 
24 #include "test_macros.h"
25 
26 std::shared_timed_mutex m;
27 
28 typedef std::chrono::system_clock Clock;
29 typedef Clock::time_point time_point;
30 typedef Clock::duration duration;
31 typedef std::chrono::milliseconds ms;
32 typedef std::chrono::nanoseconds ns;
33 
34 ms WaitTime = ms(250);
35 
36 // Thread sanitizer causes more overhead and will sometimes cause this test
37 // to fail. To prevent this we give Thread sanitizer more time to complete the
38 // test.
39 #if !defined(TEST_HAS_SANITIZERS)
40 ms Tolerance = ms(25);
41 #else
42 ms Tolerance = ms(25 * 5);
43 #endif
44 
45 
46 void f()
47 {
48     std::shared_lock<std::shared_timed_mutex> lk(m, std::defer_lock);
49     time_point t0 = Clock::now();
50     lk.lock();
51     time_point t1 = Clock::now();
52     assert(lk.owns_lock() == true);
53     ns d = t1 - t0 - WaitTime;
54     assert(d < Tolerance);  // within tolerance
55 #ifndef TEST_HAS_NO_EXCEPTIONS
56     try
57     {
58         lk.lock();
59         assert(false);
60     }
61     catch (std::system_error& e)
62     {
63         assert(e.code().value() == EDEADLK);
64     }
65 #endif
66     lk.unlock();
67     lk.release();
68 #ifndef TEST_HAS_NO_EXCEPTIONS
69     try
70     {
71         lk.lock();
72         assert(false);
73     }
74     catch (std::system_error& e)
75     {
76         assert(e.code().value() == EPERM);
77     }
78 #endif
79 }
80 
81 int main()
82 {
83     m.lock();
84     std::vector<std::thread> v;
85     for (int i = 0; i < 5; ++i)
86         v.push_back(std::thread(f));
87     std::this_thread::sleep_for(WaitTime);
88     m.unlock();
89     for (auto& t : v)
90         t.join();
91 }
92