ladybird/Libraries/LibSync/ConditionVariable.h

70 lines
1.9 KiB
C++

/*
* Copyright (c) 2021, kleines Filmröllchen <filmroellchen@serenityos.org>.
* Copyright (c) 2025, Ryszard Goc <ryszardgoc@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Concepts.h>
#include <AK/Forward.h>
#include <AK/Function.h>
#include <AK/Noncopyable.h>
#include <AK/Platform.h>
#include <LibSync/Export.h>
#include <LibSync/Mutex.h>
#include <LibSync/Policy.h>
#if !defined(AK_OS_WINDOWS)
# include <pthread.h>
#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<typename MutexType>
requires Detail::IsIntraprocess<MutexType> && Detail::IsNonRecursive<MutexType>
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<bool()> 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<typename MutexType>
ConditionVariableBase(MutexType&) -> ConditionVariableBase<MutexType>;
using ConditionVariable = ConditionVariableBase<Mutex>;
}