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 // class shared_timed_mutex; 15 16 // void lock(); 17 18 #include <shared_mutex> 19 #include <atomic> 20 #include <cassert> 21 #include <chrono> 22 #include <thread> 23 #include <vector> 24 25 #include "make_test_thread.h" 26 27 int main(int, char**) { 28 // Exclusive-lock a mutex that is not locked yet. This should succeed. 29 { 30 std::shared_timed_mutex m; 31 m.lock(); 32 m.unlock(); 33 } 34 35 // Exclusive-lock a mutex that is already locked exclusively. This should block until it is unlocked. 36 { 37 std::atomic<bool> ready(false); 38 std::shared_timed_mutex m; 39 m.lock(); 40 std::atomic<bool> is_locked_from_main(true); 41 42 std::thread t = support::make_test_thread([&] { 43 ready = true; 44 m.lock(); 45 assert(!is_locked_from_main); 46 m.unlock(); 47 }); 48 49 while (!ready) 50 /* spin */; 51 52 // We would rather signal this after we unlock, but that would create a race condition. 53 // We instead signal it before we unlock, which means that it's technically possible for the thread 54 // to take the lock while we're still holding it and for the test to still pass. 55 is_locked_from_main = false; 56 m.unlock(); 57 58 t.join(); 59 } 60 61 // Exclusive-lock a mutex that is already share-locked. This should block until it is unlocked. 62 { 63 std::atomic<bool> ready(false); 64 std::shared_timed_mutex m; 65 m.lock_shared(); 66 std::atomic<bool> is_locked_from_main(true); 67 68 std::thread t = support::make_test_thread([&] { 69 ready = true; 70 m.lock(); 71 assert(!is_locked_from_main); 72 m.unlock(); 73 }); 74 75 while (!ready) 76 /* spin */; 77 78 // We would rather signal this after we unlock, but that would create a race condition. 79 // We instead signal it before we unlock, which means that it's technically possible for 80 // the thread to take the lock while we're still holding it and for the test to still pass. 81 is_locked_from_main = false; 82 m.unlock_shared(); 83 84 t.join(); 85 } 86 87 // Make sure that at most one thread can acquire the mutex concurrently. 88 { 89 std::atomic<int> counter(0); 90 std::shared_timed_mutex mutex; 91 92 std::vector<std::thread> threads; 93 for (int i = 0; i != 10; ++i) { 94 threads.push_back(support::make_test_thread([&] { 95 mutex.lock(); 96 counter++; 97 assert(counter == 1); 98 counter--; 99 mutex.unlock(); 100 })); 101 } 102 103 for (auto& t : threads) 104 t.join(); 105 } 106 107 return 0; 108 } 109