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 "make_test_thread.h" 35 #include "test_macros.h" 36 37 typedef std::chrono::system_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 WaitTime = ms(250); 44 45 // Thread sanitizer causes more overhead and will sometimes cause this test 46 // to fail. To prevent this we give Thread sanitizer more time to complete the 47 // test. 48 #if !defined(TEST_HAS_SANITIZERS) 49 ms Tolerance = ms(50); 50 #else 51 ms Tolerance = ms(50 * 5); 52 #endif 53 54 std::shared_timed_mutex m; 55 f()56void f() 57 { 58 time_point t0 = Clock::now(); 59 time_point t1; 60 { 61 std::shared_lock<std::shared_timed_mutex> ul(m); 62 t1 = Clock::now(); 63 } 64 ns d = t1 - t0 - WaitTime; 65 assert(d < Tolerance); // within tolerance 66 } 67 g()68void g() 69 { 70 time_point t0 = Clock::now(); 71 time_point t1; 72 { 73 std::shared_lock<std::shared_timed_mutex> ul(m); 74 t1 = Clock::now(); 75 } 76 ns d = t1 - t0; 77 assert(d < Tolerance); // within tolerance 78 } 79 main(int,char **)80int main(int, char**) 81 { 82 std::vector<std::thread> v; 83 { 84 m.lock(); 85 for (int i = 0; i < 5; ++i) 86 v.push_back(support::make_test_thread(f)); 87 std::this_thread::sleep_for(WaitTime); 88 m.unlock(); 89 for (auto& t : v) 90 t.join(); 91 } 92 { 93 m.lock_shared(); 94 for (auto& t : v) 95 t = support::make_test_thread(g); 96 std::thread q = support::make_test_thread(f); 97 std::this_thread::sleep_for(WaitTime); 98 m.unlock_shared(); 99 for (auto& t : v) 100 t.join(); 101 q.join(); 102 } 103 104 #ifdef __cpp_deduction_guides 105 std::shared_lock sl(m); 106 static_assert((std::is_same<decltype(sl), std::shared_lock<decltype(m)>>::value), "" ); 107 #endif 108 109 return 0; 110 } 111