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 // <shared_mutex> 13 14 // template <class Mutex> class shared_lock; 15 16 // explicit shared_lock(mutex_type& m); 17 18 // template<class _Mutex> shared_lock(shared_lock<_Mutex>) 19 // -> shared_lock<_Mutex>; // C++17 20 21 #include <atomic> 22 #include <cassert> 23 #include <shared_mutex> 24 #include <thread> 25 #include <type_traits> 26 #include <vector> 27 28 #include "make_test_thread.h" 29 #include "test_macros.h" 30 31 struct Monitor { 32 bool lock_shared_called = false; 33 bool unlock_shared_called = false; 34 }; 35 36 struct TrackedMutex { 37 Monitor* monitor = nullptr; 38 39 void lock_shared() { 40 if (monitor != nullptr) 41 monitor->lock_shared_called = true; 42 } 43 void unlock_shared() { 44 if (monitor != nullptr) 45 monitor->unlock_shared_called = true; 46 } 47 }; 48 49 template <class Mutex> 50 void test() { 51 // Basic sanity test 52 { 53 Mutex mutex; 54 std::vector<std::thread> threads; 55 std::atomic<bool> ready(false); 56 for (int i = 0; i != 5; ++i) { 57 threads.push_back(support::make_test_thread([&] { 58 while (!ready) { 59 // spin 60 } 61 62 std::shared_lock<Mutex> lock(mutex); 63 assert(lock.owns_lock()); 64 })); 65 } 66 67 ready = true; 68 for (auto& t : threads) 69 t.join(); 70 } 71 72 // Test CTAD 73 { 74 #if TEST_STD_VER >= 17 75 Mutex mutex; 76 std::shared_lock lock(mutex); 77 static_assert(std::is_same<decltype(lock), std::shared_lock<Mutex>>::value); 78 #endif 79 } 80 } 81 82 int main(int, char**) { 83 #if TEST_STD_VER >= 17 84 test<std::shared_mutex>(); 85 #endif 86 test<std::shared_timed_mutex>(); 87 test<TrackedMutex>(); 88 89 // Use shared_lock with a dummy mutex class that tracks whether each 90 // operation has been called or not. 91 { 92 Monitor monitor; 93 TrackedMutex mutex{&monitor}; 94 95 std::shared_lock<TrackedMutex> lock(mutex); 96 assert(monitor.lock_shared_called); 97 assert(lock.owns_lock()); 98 99 lock.unlock(); 100 assert(monitor.unlock_shared_called); 101 } 102 103 return 0; 104 } 105