109 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: no-threads10// UNSUPPORTED: c++03, c++1111 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 27int 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 thread54 // 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 for80 // 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