ref: cc5182284db2880dcfc3b0bd61dbc6ed319bacc3
dir: /lib/thread/condvar+freebsd.myr/
use std use "atomic" use "mutex" use "futex" 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 aren't requeueing waiters from the condvar's futex to the mutex's futex so we can just reacquire the mutex normally. */ mtxlock(mtx) } const condsignal = {cond : cond# xadd(&cond._seq, 1) ftxwake(&cond._seq) } /* `umtx_op` fully supports implementing condvars efficiently but also requires condvars to be implemented in a specific way. For now we'll just invite the thundering herd. */ const condbroadcast = {cond : cond# xadd(&cond._seq, 1) ftxwakeall(&cond._seq) }