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 // dylib support for shared_mutex was added in macosx10.12 13 // XFAIL: with_system_cxx_lib=macosx10.11 14 // XFAIL: with_system_cxx_lib=macosx10.10 15 // XFAIL: with_system_cxx_lib=macosx10.9 16 17 // ALLOW_RETRIES: 2 18 19 // <shared_mutex> 20 21 // template <class Mutex> class shared_lock; 22 23 // explicit shared_lock(mutex_type& m); 24 25 // template<class _Mutex> shared_lock(shared_lock<_Mutex>) 26 // -> shared_lock<_Mutex>; // C++17 27 28 #include <shared_mutex> 29 #include <thread> 30 #include <vector> 31 #include <cstdlib> 32 #include <cassert> 33 34 #include "test_macros.h" 35 36 typedef std::chrono::system_clock Clock; 37 typedef Clock::time_point time_point; 38 typedef Clock::duration duration; 39 typedef std::chrono::milliseconds ms; 40 typedef std::chrono::nanoseconds ns; 41 42 ms WaitTime = ms(250); 43 44 // Thread sanitizer causes more overhead and will sometimes cause this test 45 // to fail. To prevent this we give Thread sanitizer more time to complete the 46 // test. 47 #if !defined(TEST_HAS_SANITIZERS) 48 ms Tolerance = ms(50); 49 #else 50 ms Tolerance = ms(50 * 5); 51 #endif 52 53 std::shared_timed_mutex m; 54 55 void f() 56 { 57 time_point t0 = Clock::now(); 58 time_point t1; 59 { 60 std::shared_lock<std::shared_timed_mutex> ul(m); 61 t1 = Clock::now(); 62 } 63 ns d = t1 - t0 - WaitTime; 64 assert(d < Tolerance); // within tolerance 65 } 66 67 void g() 68 { 69 time_point t0 = Clock::now(); 70 time_point t1; 71 { 72 std::shared_lock<std::shared_timed_mutex> ul(m); 73 t1 = Clock::now(); 74 } 75 ns d = t1 - t0; 76 assert(d < Tolerance); // within tolerance 77 } 78 79 int main(int, char**) 80 { 81 std::vector<std::thread> v; 82 { 83 m.lock(); 84 for (int i = 0; i < 5; ++i) 85 v.push_back(std::thread(f)); 86 std::this_thread::sleep_for(WaitTime); 87 m.unlock(); 88 for (auto& t : v) 89 t.join(); 90 } 91 { 92 m.lock_shared(); 93 for (auto& t : v) 94 t = std::thread(g); 95 std::thread q(f); 96 std::this_thread::sleep_for(WaitTime); 97 m.unlock_shared(); 98 for (auto& t : v) 99 t.join(); 100 q.join(); 101 } 102 103 #ifdef __cpp_deduction_guides 104 std::shared_lock sl(m); 105 static_assert((std::is_same<decltype(sl), std::shared_lock<decltype(m)>>::value), "" ); 106 #endif 107 108 return 0; 109 } 110