diff --git a/core/sync/sync2/extended.odin b/core/sync/sync2/extended.odin index e52da3b22..3ef4c04e5 100644 --- a/core/sync/sync2/extended.odin +++ b/core/sync/sync2/extended.odin @@ -1,5 +1,7 @@ package sync2 +import "core:time" + // A Wait_Group waits for a collection of threads to finish // // A Wait_Group must not be copied after first use @@ -45,6 +47,24 @@ wait_group_wait :: proc(wg: ^Wait_Group) { } } +wait_group_wait_with_timeout :: proc(wg: ^Wait_Group, duration: time.Duration) -> bool { + if duration <= 0 { + return false + } + mutex_lock(&wg.mutex) + defer mutex_unlock(&wg.mutex) + + if wg.counter != 0 { + if !cond_wait_with_timeout(&wg.cond, &wg.mutex, duration) { + return false + } + if wg.counter != 0 { + panic("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait") + } + } + return true +} + // A barrier enabling multiple threads to synchronize the beginning of some computation diff --git a/core/sync/sync2/sema_internal.odin b/core/sync/sync2/sema_internal.odin index 89992fbed..64fc4ed96 100644 --- a/core/sync/sync2/sema_internal.odin +++ b/core/sync/sync2/sema_internal.odin @@ -55,62 +55,18 @@ when #config(ODIN_SYNC_SEMA_USE_FUTEX, true) { } } else { _Sema :: struct { - mutex: Mutex, - cond: Cond, - count: i32, + wg: Wait_Group, } _sema_post :: proc(s: ^Sema, count := 1) { - mutex_lock(&s.impl.mutex) - defer mutex_unlock(&s.impl.mutex) - - s.impl.count += i32(count) - if count == 1 { - cond_signal(&s.impl.cond) - } else { - cond_broadcast(&s.impl.cond) - } + wait_group_add(&s.impl.wg, count) } _sema_wait :: proc(s: ^Sema) { - mutex_lock(&s.impl.mutex) - defer mutex_unlock(&s.impl.mutex) - - for s.impl.count == 0 { - cond_wait(&s.impl.cond, &s.impl.mutex) - } - - s.impl.count -= 1 - if s.impl.count > 0 { - cond_signal(&s.impl.cond) - } + wait_group_wait(&s.impl.wg) } _sema_wait_with_timeout :: proc(s: ^Sema, duration: time.Duration) -> bool { - if duration <= 0 { - return false - } - - mutex_lock(&s.impl.mutex) - defer mutex_unlock(&s.impl.mutex) - - start := time.tick_now() - for s.impl.count == 0 { - remaining := duration - time.tick_since(start) - if remaining < 0 { - return false - } - - if !cond_wait_with_timeout(&s.impl.cond, &s.impl.mutex, remaining) { - return false - } - } - - s.impl.count -= 1 - if s.impl.count > 0 { - cond_signal(&s.impl.cond) - } - - return true + return wait_group_wait_with_timeout(&s.impl.wg, duration) } } \ No newline at end of file