mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Add sync.Parker
This commit is contained in:
@@ -297,3 +297,59 @@ once_do :: proc(o: ^Once, fn: proc()) {
|
|||||||
do_slow(o, fn)
|
do_slow(o, fn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// A Parker is an associated token which is initially not present:
|
||||||
|
// * The `park` procedure blocks the current thread unless or until the token
|
||||||
|
// is available, at which point the token is consumed.
|
||||||
|
// * The `park_with_timeout` procedures works the same as `park` but only
|
||||||
|
// blocks for the specified duration.
|
||||||
|
// * The `unpark` procedure automatically makes the token available if it
|
||||||
|
// was not already.
|
||||||
|
Parker :: struct {
|
||||||
|
state: Futex,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blocks the current thread until the token is made available.
|
||||||
|
//
|
||||||
|
// Assumes this is only called by the thread that owns the Parker.
|
||||||
|
park :: proc(p: ^Parker) {
|
||||||
|
EMPTY :: 0
|
||||||
|
NOTIFIED :: 1
|
||||||
|
PARKED :: max(u32)
|
||||||
|
if atomic_sub_explicit(&p.state, 1, .Acquire) == NOTIFIED {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
futex_wait(&p.state, PARKED)
|
||||||
|
if _, ok := atomic_compare_exchange_strong_explicit(&p.state, NOTIFIED, EMPTY, .Acquire, .Acquire); ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blocks the current thread until the token is made available, but only
|
||||||
|
// for a limited duration.
|
||||||
|
//
|
||||||
|
// Assumes this is only called by the thread that owns the Parker
|
||||||
|
park_with_timeout :: proc(p: ^Parker, duration: time.Duration) {
|
||||||
|
EMPTY :: 0
|
||||||
|
NOTIFIED :: 1
|
||||||
|
PARKED :: max(u32)
|
||||||
|
if atomic_sub_explicit(&p.state, 1, .Acquire) == NOTIFIED {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
futex_wait_with_timeout(&p.state, PARKED, duration)
|
||||||
|
atomic_exchange_explicit(&p.state, EMPTY, .Acquire)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically makes thee token available if it was not already.
|
||||||
|
unpark :: proc(p: ^Parker) {
|
||||||
|
EMPTY :: 0
|
||||||
|
NOTIFIED :: 1
|
||||||
|
PARKED :: max(Futex)
|
||||||
|
if atomic_exchange_explicit(&p.state, NOTIFIED, .Release) == PARKED {
|
||||||
|
futex_signal(&p.state)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user