1*9ff04684SNikolas Klauser //===----------------------------------------------------------------------===// 2*9ff04684SNikolas Klauser // 3*9ff04684SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*9ff04684SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information. 5*9ff04684SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*9ff04684SNikolas Klauser // 7*9ff04684SNikolas Klauser //===----------------------------------------------------------------------===// 8*9ff04684SNikolas Klauser 9*9ff04684SNikolas Klauser #ifndef TEST_SUPPORT_CHECKING_MUTEX_H 10*9ff04684SNikolas Klauser #define TEST_SUPPORT_CHECKING_MUTEX_H 11*9ff04684SNikolas Klauser 12*9ff04684SNikolas Klauser #include <cassert> 13*9ff04684SNikolas Klauser #include <chrono> 14*9ff04684SNikolas Klauser 15*9ff04684SNikolas Klauser struct checking_mutex { 16*9ff04684SNikolas Klauser enum state { 17*9ff04684SNikolas Klauser locked_via_lock, 18*9ff04684SNikolas Klauser locked_via_try_lock, 19*9ff04684SNikolas Klauser locked_via_try_lock_for, 20*9ff04684SNikolas Klauser locked_via_try_lock_until, 21*9ff04684SNikolas Klauser unlocked, 22*9ff04684SNikolas Klauser none, 23*9ff04684SNikolas Klauser }; 24*9ff04684SNikolas Klauser 25*9ff04684SNikolas Klauser state current_state = unlocked; 26*9ff04684SNikolas Klauser state last_try = none; 27*9ff04684SNikolas Klauser bool reject = false; 28*9ff04684SNikolas Klauser 29*9ff04684SNikolas Klauser checking_mutex() = default; 30*9ff04684SNikolas Klauser checking_mutex(const checking_mutex&) = delete; 31*9ff04684SNikolas Klauser ~checking_mutex() { assert(current_state == unlocked); } 32*9ff04684SNikolas Klauser 33*9ff04684SNikolas Klauser void lock() { 34*9ff04684SNikolas Klauser assert(current_state == unlocked); 35*9ff04684SNikolas Klauser assert(!reject); 36*9ff04684SNikolas Klauser current_state = locked_via_lock; 37*9ff04684SNikolas Klauser last_try = locked_via_lock; 38*9ff04684SNikolas Klauser reject = true; 39*9ff04684SNikolas Klauser } 40*9ff04684SNikolas Klauser 41*9ff04684SNikolas Klauser void unlock() { 42*9ff04684SNikolas Klauser assert(current_state != unlocked && current_state != none); 43*9ff04684SNikolas Klauser last_try = unlocked; 44*9ff04684SNikolas Klauser current_state = unlocked; 45*9ff04684SNikolas Klauser reject = false; 46*9ff04684SNikolas Klauser } 47*9ff04684SNikolas Klauser 48*9ff04684SNikolas Klauser bool try_lock() { 49*9ff04684SNikolas Klauser last_try = locked_via_try_lock; 50*9ff04684SNikolas Klauser if (reject) 51*9ff04684SNikolas Klauser return false; 52*9ff04684SNikolas Klauser current_state = locked_via_try_lock; 53*9ff04684SNikolas Klauser return true; 54*9ff04684SNikolas Klauser } 55*9ff04684SNikolas Klauser 56*9ff04684SNikolas Klauser template <class Rep, class Period> 57*9ff04684SNikolas Klauser bool try_lock_for(const std::chrono::duration<Rep, Period>&) { 58*9ff04684SNikolas Klauser last_try = locked_via_try_lock_for; 59*9ff04684SNikolas Klauser if (reject) 60*9ff04684SNikolas Klauser return false; 61*9ff04684SNikolas Klauser current_state = locked_via_try_lock_for; 62*9ff04684SNikolas Klauser return true; 63*9ff04684SNikolas Klauser } 64*9ff04684SNikolas Klauser 65*9ff04684SNikolas Klauser template <class Clock, class Duration> 66*9ff04684SNikolas Klauser bool try_lock_until(const std::chrono::time_point<Clock, Duration>&) { 67*9ff04684SNikolas Klauser last_try = locked_via_try_lock_until; 68*9ff04684SNikolas Klauser if (reject) 69*9ff04684SNikolas Klauser return false; 70*9ff04684SNikolas Klauser current_state = locked_via_try_lock_until; 71*9ff04684SNikolas Klauser return true; 72*9ff04684SNikolas Klauser } 73*9ff04684SNikolas Klauser 74*9ff04684SNikolas Klauser checking_mutex* operator&() = delete; 75*9ff04684SNikolas Klauser 76*9ff04684SNikolas Klauser template <class T> 77*9ff04684SNikolas Klauser void operator,(const T&) = delete; 78*9ff04684SNikolas Klauser }; 79*9ff04684SNikolas Klauser 80*9ff04684SNikolas Klauser #endif // TEST_SUPPORT_CHECKING_MUTEX_H 81