/* * Copyright (c) 2021, kleines Filmröllchen . * Copyright (c) 2025, Ryszard Goc * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #if !defined(AK_OS_WINDOWS) # include #endif namespace Sync { // A signaling condition variable that wraps over the platform APIs. // On posix it is a wrapper of pthread_cond_*. // On Windows it wraps ConditionVariable template requires Detail::IsIntraprocess && Detail::IsNonRecursive class SYNC_API ConditionVariableBase { AK_MAKE_NONCOPYABLE(ConditionVariableBase); AK_MAKE_NONMOVABLE(ConditionVariableBase); public: ConditionVariableBase(MutexType& to_wait_on); ~ConditionVariableBase(); // As with pthread APIs, the mutex must be locked or undefined behavior ensues. // Condition variables are allowed spurious wakeups. As such waiting on a condition in a loop is preferred. void wait(); bool wait_for(AK::Duration const&); ALWAYS_INLINE void wait_while(Function condition) { while (condition()) wait(); } // Release at least one of the threads waiting on this variable. void signal(); // Release all of the threads waiting on this variable. void broadcast(); private: #ifdef AK_OS_WINDOWS using StorageType = void*; #else using StorageType = pthread_cond_t; #endif alignas(StorageType) unsigned char m_storage[sizeof(StorageType)]; MutexType& m_to_wait_on; }; template ConditionVariableBase(MutexType&) -> ConditionVariableBase; using ConditionVariable = ConditionVariableBase; }