brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.9 KiB · d36ca1d Raw
125 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// template <class Mutex> class shared_lock;15 16// void lock();17 18#include <atomic>19#include <cassert>20#include <mutex> // std::defer_lock21#include <shared_mutex>22#include <system_error>23#include <thread>24#include <vector>25 26#include "make_test_thread.h"27#include "test_macros.h"28 29struct Monitor {30  bool lock_shared_called   = false;31  bool unlock_shared_called = false;32};33 34struct TrackedMutex {35  Monitor* monitor = nullptr;36 37  void lock_shared() {38    if (monitor != nullptr)39      monitor->lock_shared_called = true;40  }41  void unlock_shared() {42    if (monitor != nullptr)43      monitor->unlock_shared_called = true;44  }45};46 47template <class Mutex>48void test() {49  // Basic sanity test50  {51    Mutex mutex;52    std::vector<std::thread> threads;53    std::atomic<bool> ready(false);54    for (int i = 0; i != 5; ++i) {55      threads.push_back(support::make_test_thread([&] {56        while (!ready) {57          // spin58        }59 60        std::shared_lock<Mutex> lock(mutex, std::defer_lock);61        lock.lock();62        assert(lock.owns_lock());63      }));64    }65 66    ready = true;67    for (auto& t : threads)68      t.join();69  }70 71  // Try locking the same shared_lock again in the same thread. This should throw an exception.72  {73    Mutex mutex;74    std::shared_lock<Mutex> lock(mutex, std::defer_lock);75    lock.lock();76    assert(lock.owns_lock());77#ifndef TEST_HAS_NO_EXCEPTIONS78    try {79      lock.lock();80      assert(false);81    } catch (std::system_error const& e) {82      assert(e.code() == std::errc::resource_deadlock_would_occur);83    }84#endif85  }86 87  // Try locking a shared_lock that isn't associated to any mutex. This should throw an exception.88  {89    std::shared_lock<Mutex> lock; // no associated mutex90#ifndef TEST_HAS_NO_EXCEPTIONS91    try {92      lock.lock();93      assert(false);94    } catch (std::system_error const& e) {95      assert(e.code() == std::errc::operation_not_permitted);96    }97#endif98  }99}100 101int main(int, char**) {102#if TEST_STD_VER >= 17103  test<std::shared_mutex>();104#endif105  test<std::shared_timed_mutex>();106  test<TrackedMutex>();107 108  // Use shared_lock with a dummy mutex class that tracks whether each109  // operation has been called or not.110  {111    Monitor monitor;112    TrackedMutex mutex{&monitor};113 114    std::shared_lock<TrackedMutex> lock(mutex, std::defer_lock);115    lock.lock();116    assert(monitor.lock_shared_called);117    assert(lock.owns_lock());118 119    lock.unlock();120    assert(monitor.unlock_shared_called);121  }122 123  return 0;124}125