ref: 7ef09f3db883c42d01e3b1d80f0d2da6ceff9913
dir: /lib/std/wait+plan9.myr/
use sys use "alloc" use "chartype" use "die" use "extremum" use "hashfuncs" use "hasprefix" use "htab" use "intparse" use "option" use "strsplit" use "striter" use "syswrap" use "utf" use "sleq" use "fmt" use "threadhooks" pkg std = type waitstatus = union `Wsuccess `Wfailure `Wsignalled `Waiterror ;; const wait : (pid : pid -> waitstatus) const waitany : (-> (pid, waitstatus)) ;; var statusmap : htab(pid, waitstatus)# const __init__ = { statusmap = mkht(inthash, inteq) } const waitany = { var buf : byte[512] var ret, it lock(envlck) if htcount(statusmap) == 0 unlock(envlck) match sys.await(buf[:]) | -1: -> (-1, `Waiterror) | n: -> parsestatus(buf[:n]) ;; else it = std.byhtkeyvals(statusmap) __iternext__(&it, &ret) unlock(envlck) -> ret ;; } const wait = {pid var buf : byte[512] var xpid, status lock(envlck) match htget(statusmap, pid) | `None: | `Some st: unlock(envlck) htdel(statusmap, pid) -> st ;; unlock(envlck) while true match sys.await(buf[:]) | -1: -> `Waiterror | n: (xpid, status) = parsestatus(buf[:n]) ;; if xpid == pid -> status else lock(envlck) htput(statusmap, xpid, status) unlock(envlck) ;; ;; /* impossible */ -> `Waiterror } const parsestatus = {status -> (pid, waitstatus) var st : waitstatus var spbuf : byte[:][5] var xpid, sp sp = bstrsplit(spbuf[:], status, " ") if sp.len == 0 -> (-1, `Wfailure) ;; match intparse(sp[0]) | `Some pid: xpid = pid /* exits(nil) => sp[0] either not present or equal to '' */ if sp.len == 4 || (sp.len == 5 && sleq(sp[4], "''")) st = `Wsuccess elif sp.len == 5 st = `Wfailure else /* we have a malformed await message */ st = `Waiterror ;; | `None: xpid = -1 st = `Waiterror ;; -> (xpid, st) }