LibSync: Implement ConditionVariable::wait_for(Duration)

This commit is contained in:
Zaggy1024 2026-05-21 21:13:43 -05:00 committed by Gregory Bertilson
parent 25dd4c6624
commit 432ec26187
3 changed files with 38 additions and 1 deletions

View file

@ -8,6 +8,7 @@
#pragma once #pragma once
#include <AK/Concepts.h> #include <AK/Concepts.h>
#include <AK/Forward.h>
#include <AK/Function.h> #include <AK/Function.h>
#include <AK/Noncopyable.h> #include <AK/Noncopyable.h>
#include <AK/Platform.h> #include <AK/Platform.h>
@ -24,7 +25,6 @@ namespace Sync {
// A signaling condition variable that wraps over the platform APIs. // A signaling condition variable that wraps over the platform APIs.
// On posix it is a wrapper of pthread_cond_*. // On posix it is a wrapper of pthread_cond_*.
// On Windows it wraps ConditionVariable // On Windows it wraps ConditionVariable
// TODO: Implement timed_wait()
template<typename MutexType> template<typename MutexType>
requires Detail::IsIntraprocess<MutexType> && Detail::IsNonRecursive<MutexType> requires Detail::IsIntraprocess<MutexType> && Detail::IsNonRecursive<MutexType>
class SYNC_API ConditionVariableBase { class SYNC_API ConditionVariableBase {
@ -38,6 +38,7 @@ public:
// As with pthread APIs, the mutex must be locked or undefined behavior ensues. // 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. // Condition variables are allowed spurious wakeups. As such waiting on a condition in a loop is preferred.
void wait(); void wait();
bool wait_for(AK::Duration const&);
ALWAYS_INLINE void wait_while(Function<bool()> condition) ALWAYS_INLINE void wait_while(Function<bool()> condition)
{ {

View file

@ -5,9 +5,11 @@
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
#include <AK/Time.h>
#include <LibSync/ConditionVariable.h> #include <LibSync/ConditionVariable.h>
#include <LibSync/Export.h> #include <LibSync/Export.h>
#include <LibSync/Mutex.h> #include <LibSync/Mutex.h>
#include <errno.h>
#include <pthread.h> #include <pthread.h>
namespace Sync { namespace Sync {
@ -47,6 +49,21 @@ void ConditionVariableBase<MutexType>::wait()
VERIFY(result == 0); VERIFY(result == 0);
} }
template<typename MutexType>
requires Detail::IsIntraprocess<MutexType> && Detail::IsNonRecursive<MutexType>
bool ConditionVariableBase<MutexType>::wait_for(AK::Duration const& timeout)
{
if (timeout <= AK::Duration::zero())
return false;
auto absolute_timeout = (AK::UnixDateTime::now() + timeout).to_timespec();
int result = pthread_cond_timedwait(to_impl(m_storage), reinterpret_cast<pthread_mutex_t*>(m_to_wait_on.m_storage), &absolute_timeout);
if (result == ETIMEDOUT)
return false;
VERIFY(result == 0);
return true;
}
template<typename MutexType> template<typename MutexType>
requires Detail::IsIntraprocess<MutexType> && Detail::IsNonRecursive<MutexType> requires Detail::IsIntraprocess<MutexType> && Detail::IsNonRecursive<MutexType>
void ConditionVariableBase<MutexType>::signal() void ConditionVariableBase<MutexType>::signal()

View file

@ -7,6 +7,7 @@
#include <AK/Assertions.h> #include <AK/Assertions.h>
#include <AK/Error.h> #include <AK/Error.h>
#include <AK/Format.h> #include <AK/Format.h>
#include <AK/Time.h>
#include <AK/Windows.h> #include <AK/Windows.h>
#include <LibSync/ConditionVariable.h> #include <LibSync/ConditionVariable.h>
#include <LibSync/Mutex.h> #include <LibSync/Mutex.h>
@ -44,6 +45,24 @@ void ConditionVariableBase<Mutex>::wait()
} }
} }
template<>
bool ConditionVariableBase<Mutex>::wait_for(AK::Duration const& timeout)
{
if (timeout <= AK::Duration::zero())
return false;
auto timeout_ms = timeout.to_milliseconds();
VERIFY(timeout_ms >= 0);
auto result = SleepConditionVariableSRW(to_impl(m_storage), reinterpret_cast<PSRWLOCK>(m_to_wait_on.m_storage), static_cast<DWORD>(min<i64>(timeout_ms, INFINITE - 1)), 0);
if (result)
return true;
auto error = GetLastError();
if (error == ERROR_TIMEOUT)
return false;
warnln("SleepConditionVariableSRW failed with: {}", Error::from_windows_error(error));
VERIFY_NOT_REACHED();
}
template<typename MutexType> template<typename MutexType>
requires Detail::IsIntraprocess<MutexType> && Detail::IsNonRecursive<MutexType> requires Detail::IsIntraprocess<MutexType> && Detail::IsNonRecursive<MutexType>
void ConditionVariableBase<MutexType>::signal() void ConditionVariableBase<MutexType>::signal()