diff --git a/core/sync/sync2/primitives_atomic.odin b/core/sync/sync2/primitives_atomic.odin index 94a336a60..94db980a5 100644 --- a/core/sync/sync2/primitives_atomic.odin +++ b/core/sync/sync2/primitives_atomic.odin @@ -1,5 +1,7 @@ package sync2 +import "core:time" + Atomic_Mutex_State :: enum Futex { Unlocked = 0, Locked = 1, @@ -298,6 +300,21 @@ queue_item_wait :: proc(item: ^Queue_Item) { } } @(private="file") +queue_item_wait_with_timeout :: proc(item: ^Queue_Item, duration: time.Duration) -> bool { + start := time.tick_now() + for atomic_load_acquire(&item.futex) == 0 { + remaining := duration - time.tick_since(start) + if remaining < 0 { + return false + } + if futex_wait_with_timeout(&item.futex, 0, remaining) == .Timed_Out { + return false + } + cpu_relax() + } + return true +} +@(private="file") queue_item_signal :: proc(item: ^Queue_Item) { atomic_store_release(&item.futex, 1) futex_wake_single(&item.futex) @@ -329,6 +346,23 @@ atomic_cond_wait :: proc(c: ^Atomic_Cond, m: ^Atomic_Mutex) { atomic_mutex_lock(m) } +atomic_cond_wait_with_timeout :: proc(c: ^Atomic_Cond, m: ^Atomic_Mutex, duration: time.Duration) -> (ok: bool) { + waiter := &Queue_Item{} + + atomic_mutex_lock(&c.queue_mutex) + waiter.next = c.queue_head + c.queue_head = waiter + + atomic_store(&c.pending, true) + atomic_mutex_unlock(&c.queue_mutex) + + atomic_mutex_unlock(m) + ok = queue_item_wait_with_timeout(waiter, duration) + atomic_mutex_lock(m) + return +} + + atomic_cond_signal :: proc(c: ^Atomic_Cond) { if !atomic_load(&c.pending) { return diff --git a/core/sync/sync2/primitives_darwin.odin b/core/sync/sync2/primitives_darwin.odin index bd9b0e267..66995bd01 100644 --- a/core/sync/sync2/primitives_darwin.odin +++ b/core/sync/sync2/primitives_darwin.odin @@ -45,9 +45,7 @@ _cond_wait :: proc(c: ^Cond, m: ^Mutex) { } _cond_wait_with_timeout :: proc(c: ^Cond, m: ^Mutex, duration: time.Duration) -> bool { - // TODO(bill): _cond_wait_with_timeout for Darwin - atomic_cond_wait(&c.impl.cond, &m.impl.mutex) - return true + return atomic_cond_wait_with_timeout(&c.impl.cond, &m.impl.mutex, duration) } _cond_signal :: proc(c: ^Cond) {