158 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++11, c++1411 12// <mutex>13 14// template <class ...Mutex> class scoped_lock;15 16// explicit scoped_lock(mutex_type& m);17 18#include <mutex>19#include <cassert>20#include "test_macros.h"21 22struct TestMutex {23 bool locked = false;24 TestMutex() = default;25 ~TestMutex() { assert(!locked); }26 27 void lock() { assert(!locked); locked = true; }28 bool try_lock() { if (locked) return false; locked = true; return true; }29 void unlock() { assert(locked); locked = false; }30 31 TestMutex(TestMutex const&) = delete;32 TestMutex& operator=(TestMutex const&) = delete;33};34 35#if !defined(TEST_HAS_NO_EXCEPTIONS)36struct TestMutexThrows {37 bool locked = false;38 bool throws_on_lock = false;39 40 TestMutexThrows() = default;41 ~TestMutexThrows() { assert(!locked); }42 43 void lock() {44 assert(!locked);45 if (throws_on_lock) {46 throw 42;47 }48 locked = true;49 }50 51 bool try_lock() {52 if (locked) return false;53 lock();54 return true;55 }56 57 void unlock() { assert(locked); locked = false; }58 59 TestMutexThrows(TestMutexThrows const&) = delete;60 TestMutexThrows& operator=(TestMutexThrows const&) = delete;61};62#endif // !defined(TEST_HAS_NO_EXCEPTIONS)63 64int main(int, char**)65{66 {67 using LG = std::scoped_lock<>;68 LG lg;69 (void)lg;70 }71 {72 using LG = std::scoped_lock<TestMutex>;73 TestMutex m1;74 {75 LG lg(m1);76 assert(m1.locked);77 }78 assert(!m1.locked);79 }80 {81 using LG = std::scoped_lock<TestMutex, TestMutex>;82 TestMutex m1, m2;83 {84 LG lg(m1, m2);85 assert(m1.locked && m2.locked);86 }87 assert(!m1.locked && !m2.locked);88 }89 {90 using LG = std::scoped_lock<TestMutex, TestMutex, TestMutex>;91 TestMutex m1, m2, m3;92 {93 LG lg(m1, m2, m3);94 assert(m1.locked && m2.locked && m3.locked);95 }96 assert(!m1.locked && !m2.locked && !m3.locked);97 }98#if !defined(TEST_HAS_NO_EXCEPTIONS)99 {100 using MT = TestMutexThrows;101 using LG = std::scoped_lock<MT>;102 MT m1;103 m1.throws_on_lock = true;104 try {105 LG lg(m1);106 assert(false);107 } catch (int) {}108 assert(!m1.locked);109 }110 {111 using MT = TestMutexThrows;112 using LG = std::scoped_lock<MT, MT>;113 MT m1, m2;114 m1.throws_on_lock = true;115 try {116 LG lg(m1, m2);117 assert(false);118 } catch (int) {}119 assert(!m1.locked && !m2.locked);120 }121 {122 using MT = TestMutexThrows;123 using LG = std::scoped_lock<MT, MT, MT>;124 MT m1, m2, m3;125 m2.throws_on_lock = true;126 try {127 LG lg(m1, m2, m3);128 assert(false);129 } catch (int) {}130 assert(!m1.locked && !m2.locked && !m3.locked);131 }132#endif133 134#if TEST_STD_VER >= 17135 {136 TestMutex m1, m2, m3;137 {138 std::scoped_lock sl{};139 static_assert((std::is_same<decltype(sl), std::scoped_lock<>>::value), "" );140 }141 {142 std::scoped_lock sl{m1};143 static_assert((std::is_same<decltype(sl), std::scoped_lock<decltype(m1)>>::value), "" );144 }145 {146 std::scoped_lock sl{m1, m2};147 static_assert((std::is_same<decltype(sl), std::scoped_lock<decltype(m1), decltype(m2)>>::value), "" );148 }149 {150 std::scoped_lock sl{m1, m2, m3};151 static_assert((std::is_same<decltype(sl), std::scoped_lock<decltype(m1), decltype(m2), decltype(m3)>>::value), "" );152 }153 }154#endif155 156 return 0;157}158