16015dd11SMarshall Clow //===----------------------------------------------------------------------===//
26015dd11SMarshall Clow //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66015dd11SMarshall Clow //
76015dd11SMarshall Clow //===----------------------------------------------------------------------===//
86015dd11SMarshall Clow //
9*a7f9895cSLouis Dionne // UNSUPPORTED: no-threads
1031cbe0f2SLouis Dionne // UNSUPPORTED: c++03, c++11, c++14
116015dd11SMarshall Clow
126015dd11SMarshall Clow // <mutex>
136015dd11SMarshall Clow
146015dd11SMarshall Clow // template <class ...Mutex> class scoped_lock;
156015dd11SMarshall Clow
166015dd11SMarshall Clow // explicit scoped_lock(mutex_type& m);
176015dd11SMarshall Clow
186015dd11SMarshall Clow #include <mutex>
196015dd11SMarshall Clow #include <cassert>
206015dd11SMarshall Clow #include "test_macros.h"
216015dd11SMarshall Clow
226015dd11SMarshall Clow struct TestMutex {
236015dd11SMarshall Clow bool locked = false;
246015dd11SMarshall Clow TestMutex() = default;
~TestMutexTestMutex256015dd11SMarshall Clow ~TestMutex() { assert(!locked); }
266015dd11SMarshall Clow
lockTestMutex276015dd11SMarshall Clow void lock() { assert(!locked); locked = true; }
try_lockTestMutex286015dd11SMarshall Clow bool try_lock() { if (locked) return false; locked = true; return true; }
unlockTestMutex296015dd11SMarshall Clow void unlock() { assert(locked); locked = false; }
306015dd11SMarshall Clow
316015dd11SMarshall Clow TestMutex(TestMutex const&) = delete;
326015dd11SMarshall Clow TestMutex& operator=(TestMutex const&) = delete;
336015dd11SMarshall Clow };
346015dd11SMarshall Clow
356015dd11SMarshall Clow #if !defined(TEST_HAS_NO_EXCEPTIONS)
366015dd11SMarshall Clow struct TestMutexThrows {
376015dd11SMarshall Clow bool locked = false;
386015dd11SMarshall Clow bool throws_on_lock = false;
396015dd11SMarshall Clow
406015dd11SMarshall Clow TestMutexThrows() = default;
~TestMutexThrowsTestMutexThrows416015dd11SMarshall Clow ~TestMutexThrows() { assert(!locked); }
426015dd11SMarshall Clow
lockTestMutexThrows436015dd11SMarshall Clow void lock() {
446015dd11SMarshall Clow assert(!locked);
456015dd11SMarshall Clow if (throws_on_lock) {
466015dd11SMarshall Clow throw 42;
476015dd11SMarshall Clow }
486015dd11SMarshall Clow locked = true;
496015dd11SMarshall Clow }
506015dd11SMarshall Clow
try_lockTestMutexThrows516015dd11SMarshall Clow bool try_lock() {
526015dd11SMarshall Clow if (locked) return false;
536015dd11SMarshall Clow lock();
546015dd11SMarshall Clow return true;
556015dd11SMarshall Clow }
566015dd11SMarshall Clow
unlockTestMutexThrows576015dd11SMarshall Clow void unlock() { assert(locked); locked = false; }
586015dd11SMarshall Clow
596015dd11SMarshall Clow TestMutexThrows(TestMutexThrows const&) = delete;
606015dd11SMarshall Clow TestMutexThrows& operator=(TestMutexThrows const&) = delete;
616015dd11SMarshall Clow };
626015dd11SMarshall Clow #endif // !defined(TEST_HAS_NO_EXCEPTIONS)
636015dd11SMarshall Clow
main(int,char **)642df59c50SJF Bastien int main(int, char**)
656015dd11SMarshall Clow {
666015dd11SMarshall Clow {
676015dd11SMarshall Clow using LG = std::scoped_lock<>;
686015dd11SMarshall Clow LG lg;
696015dd11SMarshall Clow }
706015dd11SMarshall Clow {
716015dd11SMarshall Clow using LG = std::scoped_lock<TestMutex>;
726015dd11SMarshall Clow TestMutex m1;
736015dd11SMarshall Clow {
746015dd11SMarshall Clow LG lg(m1);
756015dd11SMarshall Clow assert(m1.locked);
766015dd11SMarshall Clow }
776015dd11SMarshall Clow assert(!m1.locked);
786015dd11SMarshall Clow }
796015dd11SMarshall Clow {
806015dd11SMarshall Clow using LG = std::scoped_lock<TestMutex, TestMutex>;
816015dd11SMarshall Clow TestMutex m1, m2;
826015dd11SMarshall Clow {
836015dd11SMarshall Clow LG lg(m1, m2);
846015dd11SMarshall Clow assert(m1.locked && m2.locked);
856015dd11SMarshall Clow }
866015dd11SMarshall Clow assert(!m1.locked && !m2.locked);
876015dd11SMarshall Clow }
886015dd11SMarshall Clow {
896015dd11SMarshall Clow using LG = std::scoped_lock<TestMutex, TestMutex, TestMutex>;
906015dd11SMarshall Clow TestMutex m1, m2, m3;
916015dd11SMarshall Clow {
926015dd11SMarshall Clow LG lg(m1, m2, m3);
936015dd11SMarshall Clow assert(m1.locked && m2.locked && m3.locked);
946015dd11SMarshall Clow }
956015dd11SMarshall Clow assert(!m1.locked && !m2.locked && !m3.locked);
966015dd11SMarshall Clow }
976015dd11SMarshall Clow #if !defined(TEST_HAS_NO_EXCEPTIONS)
986015dd11SMarshall Clow {
996015dd11SMarshall Clow using MT = TestMutexThrows;
1006015dd11SMarshall Clow using LG = std::scoped_lock<MT>;
1016015dd11SMarshall Clow MT m1;
1026015dd11SMarshall Clow m1.throws_on_lock = true;
1036015dd11SMarshall Clow try {
1046015dd11SMarshall Clow LG lg(m1);
1056015dd11SMarshall Clow assert(false);
1066015dd11SMarshall Clow } catch (int) {}
1076015dd11SMarshall Clow assert(!m1.locked);
1086015dd11SMarshall Clow }
1096015dd11SMarshall Clow {
1106015dd11SMarshall Clow using MT = TestMutexThrows;
1116015dd11SMarshall Clow using LG = std::scoped_lock<MT, MT>;
1126015dd11SMarshall Clow MT m1, m2;
1136015dd11SMarshall Clow m1.throws_on_lock = true;
1146015dd11SMarshall Clow try {
1156015dd11SMarshall Clow LG lg(m1, m2);
1166015dd11SMarshall Clow assert(false);
1176015dd11SMarshall Clow } catch (int) {}
1186015dd11SMarshall Clow assert(!m1.locked && !m2.locked);
1196015dd11SMarshall Clow }
1206015dd11SMarshall Clow {
1216015dd11SMarshall Clow using MT = TestMutexThrows;
1226015dd11SMarshall Clow using LG = std::scoped_lock<MT, MT, MT>;
1236015dd11SMarshall Clow MT m1, m2, m3;
1246015dd11SMarshall Clow m2.throws_on_lock = true;
1256015dd11SMarshall Clow try {
1266015dd11SMarshall Clow LG lg(m1, m2, m3);
1276015dd11SMarshall Clow assert(false);
1286015dd11SMarshall Clow } catch (int) {}
1296015dd11SMarshall Clow assert(!m1.locked && !m2.locked && !m3.locked);
1306015dd11SMarshall Clow }
1316015dd11SMarshall Clow #endif
1326015dd11SMarshall Clow
13301666904SLouis Dionne #if TEST_STD_VER >= 17
1346015dd11SMarshall Clow {
1356015dd11SMarshall Clow TestMutex m1, m2, m3;
1366015dd11SMarshall Clow {
1376015dd11SMarshall Clow std::scoped_lock sl{};
1386015dd11SMarshall Clow static_assert((std::is_same<decltype(sl), std::scoped_lock<>>::value), "" );
1396015dd11SMarshall Clow }
1406015dd11SMarshall Clow {
1416015dd11SMarshall Clow std::scoped_lock sl{m1};
1426015dd11SMarshall Clow static_assert((std::is_same<decltype(sl), std::scoped_lock<decltype(m1)>>::value), "" );
1436015dd11SMarshall Clow }
1446015dd11SMarshall Clow {
1456015dd11SMarshall Clow std::scoped_lock sl{m1, m2};
1466015dd11SMarshall Clow static_assert((std::is_same<decltype(sl), std::scoped_lock<decltype(m1), decltype(m2)>>::value), "" );
1476015dd11SMarshall Clow }
1486015dd11SMarshall Clow {
1496015dd11SMarshall Clow std::scoped_lock sl{m1, m2, m3};
1506015dd11SMarshall Clow static_assert((std::is_same<decltype(sl), std::scoped_lock<decltype(m1), decltype(m2), decltype(m3)>>::value), "" );
1516015dd11SMarshall Clow }
1526015dd11SMarshall Clow }
1536015dd11SMarshall Clow #endif
1542df59c50SJF Bastien
1552df59c50SJF Bastien return 0;
1566015dd11SMarshall Clow }
157