//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // UNSUPPORTED: no-threads // This test hangs forever when built against libstdc++ (Oct 2016). // UNSUPPORTED: stdlib=libstdc++ // This test isn't quite standards-conforming: it's testing our specific // algorithm, where when lx.try_lock() fails we start the next attempt // with an unconditional lx.lock(). Thus our algorithm can handle a list // of mutexes where at-most-one of them is of the evil type `class L1`, // but will loop forever if two or more of them are `class L1`. // // template // void lock(L1&, L2&, L3&...); #include #include #include "test_macros.h" class L0 { bool locked_; public: L0() : locked_(false) {} void lock() { locked_ = true; } bool try_lock() { locked_ = true; return locked_; } void unlock() {locked_ = false;} bool locked() const {return locked_;} }; class L1 { bool locked_; public: L1() : locked_(false) {} void lock() { locked_ = true; } bool try_lock() { locked_ = false; return locked_; } void unlock() {locked_ = false;} bool locked() const {return locked_;} }; class L2 { bool locked_; public: L2() : locked_(false) {} void lock() { TEST_THROW(1); } bool try_lock() { TEST_THROW(1); return locked_; } void unlock() {locked_ = false;} bool locked() const {return locked_;} }; int main(int, char**) { { L0 l0; L0 l1; std::lock(l0, l1); assert(l0.locked()); assert(l1.locked()); } { L0 l0; L1 l1; std::lock(l0, l1); assert(l0.locked()); assert(l1.locked()); } { L1 l0; L0 l1; std::lock(l0, l1); assert(l0.locked()); assert(l1.locked()); } #ifndef TEST_HAS_NO_EXCEPTIONS { L0 l0; L2 l1; try { std::lock(l0, l1); assert(false); } catch (int) { assert(!l0.locked()); assert(!l1.locked()); } } { L2 l0; L0 l1; try { std::lock(l0, l1); assert(false); } catch (int) { assert(!l0.locked()); assert(!l1.locked()); } } { L1 l0; L2 l1; try { std::lock(l0, l1); assert(false); } catch (int) { assert(!l0.locked()); assert(!l1.locked()); } } { L2 l0; L1 l1; try { std::lock(l0, l1); assert(false); } catch (int) { assert(!l0.locked()); assert(!l1.locked()); } } { L2 l0; L2 l1; try { std::lock(l0, l1); assert(false); } catch (int) { assert(!l0.locked()); assert(!l1.locked()); } } #endif #if TEST_STD_VER >= 11 { L0 l0; L0 l1; L0 l2; std::lock(l0, l1, l2); assert(l0.locked()); assert(l1.locked()); assert(l2.locked()); } #ifndef TEST_HAS_NO_EXCEPTIONS { L2 l0; L2 l1; L2 l2; try { std::lock(l0, l1, l2); assert(false); } catch (int) { assert(!l0.locked()); assert(!l1.locked()); assert(!l2.locked()); } } #endif { L0 l0; L0 l1; L1 l2; std::lock(l0, l1, l2); assert(l0.locked()); assert(l1.locked()); assert(l2.locked()); } { L0 l0; L1 l1; L0 l2; std::lock(l0, l1, l2); assert(l0.locked()); assert(l1.locked()); assert(l2.locked()); } { L1 l0; L0 l1; L0 l2; std::lock(l0, l1, l2); assert(l0.locked()); assert(l1.locked()); assert(l2.locked()); } #ifndef TEST_HAS_NO_EXCEPTIONS { L0 l0; L0 l1; L2 l2; try { std::lock(l0, l1, l2); assert(false); } catch (int) { assert(!l0.locked()); assert(!l1.locked()); assert(!l2.locked()); } } { L0 l0; L2 l1; L0 l2; try { std::lock(l0, l1, l2); assert(false); } catch (int) { assert(!l0.locked()); assert(!l1.locked()); assert(!l2.locked()); } } { L2 l0; L0 l1; L0 l2; try { std::lock(l0, l1, l2); assert(false); } catch (int) { assert(!l0.locked()); assert(!l1.locked()); assert(!l2.locked()); } } { L2 l0; L2 l1; L0 l2; try { std::lock(l0, l1, l2); assert(false); } catch (int) { assert(!l0.locked()); assert(!l1.locked()); assert(!l2.locked()); } } { L2 l0; L0 l1; L2 l2; try { std::lock(l0, l1, l2); assert(false); } catch (int) { assert(!l0.locked()); assert(!l1.locked()); assert(!l2.locked()); } } { L0 l0; L2 l1; L2 l2; try { std::lock(l0, l1, l2); assert(false); } catch (int) { assert(!l0.locked()); assert(!l1.locked()); assert(!l2.locked()); } } { L2 l0; L2 l1; L1 l2; try { std::lock(l0, l1, l2); assert(false); } catch (int) { assert(!l0.locked()); assert(!l1.locked()); assert(!l2.locked()); } } { L2 l0; L1 l1; L2 l2; try { std::lock(l0, l1, l2); assert(false); } catch (int) { assert(!l0.locked()); assert(!l1.locked()); assert(!l2.locked()); } } { L1 l0; L2 l1; L2 l2; try { std::lock(l0, l1, l2); assert(false); } catch (int) { assert(!l0.locked()); assert(!l1.locked()); assert(!l2.locked()); } } #endif // TEST_HAS_NO_EXCEPTIONS { L0 l0; L0 l1; L0 l2; L0 l3; std::lock(l0, l1, l2, l3); assert(l0.locked()); assert(l1.locked()); assert(l2.locked()); assert(l3.locked()); } { L0 l0; L0 l1; L0 l2; L1 l3; std::lock(l0, l1, l2, l3); assert(l0.locked()); assert(l1.locked()); assert(l2.locked()); assert(l3.locked()); } { L0 l0; L0 l1; L1 l2; L0 l3; std::lock(l0, l1, l2, l3); assert(l0.locked()); assert(l1.locked()); assert(l2.locked()); assert(l3.locked()); } { L0 l0; L1 l1; L0 l2; L0 l3; std::lock(l0, l1, l2, l3); assert(l0.locked()); assert(l1.locked()); assert(l2.locked()); assert(l3.locked()); } { L1 l0; L0 l1; L0 l2; L0 l3; std::lock(l0, l1, l2, l3); assert(l0.locked()); assert(l1.locked()); assert(l2.locked()); assert(l3.locked()); } #ifndef TEST_HAS_NO_EXCEPTIONS { L0 l0; L0 l1; L0 l2; L2 l3; try { std::lock(l0, l1, l2, l3); assert(false); } catch (int) { assert(!l0.locked()); assert(!l1.locked()); assert(!l2.locked()); assert(!l3.locked()); } } { L0 l0; L0 l1; L2 l2; L0 l3; try { std::lock(l0, l1, l2, l3); assert(false); } catch (int) { assert(!l0.locked()); assert(!l1.locked()); assert(!l2.locked()); assert(!l3.locked()); } } { L0 l0; L2 l1; L0 l2; L0 l3; try { std::lock(l0, l1, l2, l3); assert(false); } catch (int) { assert(!l0.locked()); assert(!l1.locked()); assert(!l2.locked()); assert(!l3.locked()); } } { L2 l0; L0 l1; L0 l2; L0 l3; try { std::lock(l0, l1, l2, l3); assert(false); } catch (int) { assert(!l0.locked()); assert(!l1.locked()); assert(!l2.locked()); assert(!l3.locked()); } } #endif // TEST_HAS_NO_EXCEPTIONS #endif // TEST_STD_VER >= 11 return 0; }