mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
Add wait_group_wait_with_timeout; Allow Sema to be implemented as a Wait_Group
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
package sync2
|
package sync2
|
||||||
|
|
||||||
|
import "core:time"
|
||||||
|
|
||||||
// A Wait_Group waits for a collection of threads to finish
|
// A Wait_Group waits for a collection of threads to finish
|
||||||
//
|
//
|
||||||
// A Wait_Group must not be copied after first use
|
// 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
|
// A barrier enabling multiple threads to synchronize the beginning of some computation
|
||||||
|
|||||||
@@ -55,62 +55,18 @@ when #config(ODIN_SYNC_SEMA_USE_FUTEX, true) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_Sema :: struct {
|
_Sema :: struct {
|
||||||
mutex: Mutex,
|
wg: Wait_Group,
|
||||||
cond: Cond,
|
|
||||||
count: i32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_sema_post :: proc(s: ^Sema, count := 1) {
|
_sema_post :: proc(s: ^Sema, count := 1) {
|
||||||
mutex_lock(&s.impl.mutex)
|
wait_group_add(&s.impl.wg, count)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_sema_wait :: proc(s: ^Sema) {
|
_sema_wait :: proc(s: ^Sema) {
|
||||||
mutex_lock(&s.impl.mutex)
|
wait_group_wait(&s.impl.wg)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_sema_wait_with_timeout :: proc(s: ^Sema, duration: time.Duration) -> bool {
|
_sema_wait_with_timeout :: proc(s: ^Sema, duration: time.Duration) -> bool {
|
||||||
if duration <= 0 {
|
return wait_group_wait_with_timeout(&s.impl.wg, duration)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user