LibSync: Implement ConditionVariable::wait_for(Duration)
This commit is contained in:
parent
25dd4c6624
commit
432ec26187
3 changed files with 38 additions and 1 deletions
|
|
@ -8,6 +8,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Concepts.h>
|
||||
#include <AK/Forward.h>
|
||||
#include <AK/Function.h>
|
||||
#include <AK/Noncopyable.h>
|
||||
#include <AK/Platform.h>
|
||||
|
|
@ -24,7 +25,6 @@ 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
|
||||
// TODO: Implement timed_wait()
|
||||
template<typename MutexType>
|
||||
requires Detail::IsIntraprocess<MutexType> && Detail::IsNonRecursive<MutexType>
|
||||
class SYNC_API ConditionVariableBase {
|
||||
|
|
@ -38,6 +38,7 @@ public:
|
|||
// 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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,9 +5,11 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/Time.h>
|
||||
#include <LibSync/ConditionVariable.h>
|
||||
#include <LibSync/Export.h>
|
||||
#include <LibSync/Mutex.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
namespace Sync {
|
||||
|
|
@ -47,6 +49,21 @@ void ConditionVariableBase<MutexType>::wait()
|
|||
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>
|
||||
requires Detail::IsIntraprocess<MutexType> && Detail::IsNonRecursive<MutexType>
|
||||
void ConditionVariableBase<MutexType>::signal()
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <AK/Assertions.h>
|
||||
#include <AK/Error.h>
|
||||
#include <AK/Format.h>
|
||||
#include <AK/Time.h>
|
||||
#include <AK/Windows.h>
|
||||
#include <LibSync/ConditionVariable.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>
|
||||
requires Detail::IsIntraprocess<MutexType> && Detail::IsNonRecursive<MutexType>
|
||||
void ConditionVariableBase<MutexType>::signal()
|
||||
|
|
|
|||
Loading…
Reference in a new issue