ref: 4da95e96e01dac40ff290b1e2cb4e9f641aea398
dir: /lib/thread/condvar+linux.myr/
use std use sys use "atomic" use "common" use "futex" use "mutex" pkg thread = type cond = struct _mtx : mutex# _seq : ftxtag ;; const mkcond : (mtx : mutex# -> cond) const condwait : (cond : cond# -> void) const condsignal : (cond : cond# -> void) const condbroadcast : (cond : cond# -> void) ;; const mkcond = {mtx -> [._mtx = mtx, ._seq = 0] } const condwait = {cond var mtx = cond._mtx var seq = xget(&cond._seq) mtxunlock(mtx) ftxwait(&cond._seq, seq, -1) /* In the event of a broadcast, we need to atomically set the mutex to contended. This allows us to pass responsibility for waking up the potential other waiters from the requeue operation on to the unlocker of the mutex. */ mtxcontended(mtx) } const condsignal = {cond : cond# xadd(&cond._seq, 1) ftxwake(&cond._seq) } const condbroadcast = {cond : cond# xadd(&cond._seq, 1) /* The futex docs seem to be broken -- the timeout parameter seems to be used for the number of threads to move, and is not ignored when requeueing */ sys.futex((&cond._seq : int32#), sys.Futexrequeue | sys.Futexpriv, 1, (0x7fffffff : sys.timespec#), (&cond._mtx._state : int32#), 0) }