Add ConditionVariable.wait_until and ConditionVariable.wait_for (#2302)

* Add `ConditionVariable.wait_until` and `ConditionVariable.wait_for`
* Add "@structlike" for typedefs.

---------

Co-authored-by: Christoffer Lerno <christoffer@aegik.com>
This commit is contained in:
Christian Buttner
2025-07-19 13:12:14 +02:00
committed by GitHub
parent 448176b0b7
commit 2053f2767b
18 changed files with 104 additions and 36 deletions

View File

@@ -142,12 +142,26 @@ fn void? NativeConditionVariable.wait(&cond, NativeMutex* mtx)
*>
fn void? NativeConditionVariable.wait_timeout(&cond, NativeMutex* mtx, ulong ms)
{
TimeSpec now;
if (libc::timespec_get(&now, libc::TIME_UTC) != libc::TIME_UTC) return thread::WAIT_FAILED?;
now.ns += (CLong)((ms % 1000) * 1000_000);
now.s += (Time_t)(ms / 1000 + now.ns / 1000_000_000);
now.ns = now.ns % 1000_000_000;
switch (posix::pthread_cond_timedwait(cond, &mtx.mutex, &now))
Time time = time::now() + time::ms(ms);
return cond.wait_until(mtx, time) @inline;
}
<*
@require mtx.is_initialized()
*>
fn void? NativeConditionVariable.wait_timeout_duration(&cond, NativeMutex* mtx, Duration duration)
{
if (duration < time::DURATION_ZERO) return thread::WAIT_TIMEOUT?;
Time time = time::now() + duration;
return cond.wait_until(mtx, time) @inline;
}
<*
@require mtx.is_initialized()
*>
fn void? NativeConditionVariable.wait_until(&cond, NativeMutex* mtx, Time time)
{
switch (posix::pthread_cond_timedwait(cond, &mtx.mutex, &&time.to_timespec()))
{
case errno::ETIMEDOUT:
return thread::WAIT_TIMEOUT?;
@@ -216,7 +230,7 @@ fn void native_thread_yield()
fn void? native_sleep_nano(NanoDuration nano)
{
if (nano <= 0) return;
if (nano <= time::NANO_DURATION_ZERO) return;
if (libc::nanosleep(&&nano.to_timespec(), null)) return thread::INTERRUPTED?;
}

View File

@@ -198,7 +198,7 @@ fn void? NativeTimedMutex.lock_timeout(&mtx, ulong ms)
NanoDuration duration = time::ms(ms).to_nano();
Clock start = clock::now();
for (NanoDuration remaining = duration; remaining > 0; remaining = duration - start.to_now())
for (NanoDuration remaining = duration; remaining > time::NANO_DURATION_ZERO; remaining = duration - start.to_now())
{
ulong remaining_ms = remaining.to_ms();
if (remaining_ms > uint.max) remaining_ms = uint.max;
@@ -318,6 +318,26 @@ fn void? NativeConditionVariable.wait_timeout(&cond, NativeMutex* mtx, ulong ms)
return timedwait(cond, mtx, (uint)ms) @inline;
}
<*
@require mtx.initialized : "Mutex was not initialized"
*>
fn void? NativeConditionVariable.wait_timeout_duration(&cond, NativeMutex* mtx, Duration duration) @inline
{
if (duration < time::DURATION_ZERO) return thread::WAIT_TIMEOUT?;
long ms = duration.to_ms();
if (ms > uint.max) ms = uint.max;
return timedwait(cond, mtx, (uint)ms) @inline;
}
<*
@require mtx.initialized : "Mutex was not initialized"
*>
fn void? NativeConditionVariable.wait_until(&cond, NativeMutex* mtx, Time time) @inline
{
Duration duration = time - time::now();
return cond.wait_timeout_duration(mtx, duration);
}
fn void? NativeThread.create(&thread, ThreadFn func, void* args)
{
if (!(*thread = (NativeThread)win32::createThread(null, 0, func, args, 0, null))) return thread::INIT_FAILED?;

View File

@@ -63,9 +63,21 @@ macro void? ConditionVariable.wait(&cond, Mutex* mutex)
{
return NativeConditionVariable.wait((NativeConditionVariable*)cond, (NativeMutex*)mutex);
}
macro void? ConditionVariable.wait_timeout(&cond, Mutex* mutex, ulong ms)
<*
@require @assignable_to(#ms_or_duration, Duration) || @assignable_to(#ms_or_duration, ulong)
*>
macro void? ConditionVariable.wait_timeout(&cond, Mutex* mutex, #ms_or_duration) @safemacro
{
return NativeConditionVariable.wait_timeout((NativeConditionVariable*)cond, (NativeMutex*)mutex, ms);
$if @implicit_to(#ms_or_duration):
return NativeConditionVariable.wait_timeout_duration((NativeConditionVariable*)cond, (NativeMutex*)mutex, #ms_or_duration);
$else
return NativeConditionVariable.wait_timeout((NativeConditionVariable*)cond, (NativeMutex*)mutex, #ms_or_duration);
$endif
}
macro void? ConditionVariable.wait_until(&cond, Mutex* mutex, Time time)
{
return NativeConditionVariable.wait_until((NativeConditionVariable*)cond, (NativeMutex*)mutex, time);
}
<*