diff options
Diffstat (limited to 'lib/std/wait+plan9.myr')
-rw-r--r-- | lib/std/wait+plan9.myr | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/lib/std/wait+plan9.myr b/lib/std/wait+plan9.myr new file mode 100644 index 0000000..efe1a1c --- /dev/null +++ b/lib/std/wait+plan9.myr @@ -0,0 +1,94 @@ +use sys + +use "alloc.use" +use "chartype.use" +use "die.use" +use "extremum.use" +use "hashfuncs.use" +use "hasprefix.use" +use "htab.use" +use "intparse.use" +use "option.use" +use "strsplit.use" +use "syswrap.use" +use "utf.use" + +pkg std = + type waitstatus = union + `Wsuccess + `Wfailure + `Wsignalled + `Waiterror + ;; + + const wait : (pid : pid -> waitstatus) +;; + +var statusinit : bool = false +var statusmap : htab(pid, waitstatus)# + +const wait = {pid + var buf : byte[512] + var xpid, status + var n + + if !statusinit + statusmap = mkht(pidhash, pideq) + statusinit = true + ;; + + match htget(statusmap, pid) + | `Some st: + htdel(statusmap, pid) + -> st + | `None: /* nothing */ + ;; + + while true + n = sys.await(buf[:]) + if n < 0 + -> `Waiterror + ;; + + (status, xpid) = parsestatus(buf[:n]) + if xpid == pid + -> status + else + htput(statusmap, pid, status) + ;; + ;; + /* impossible */ + -> `Waiterror +} + +const parsestatus = {status -> (waitstatus, pid) + var st : waitstatus, xpid, sp + + sp = strsplit(status, " ") + if sp.len == 0 + slfree(sp) + -> (`Wfailure, -1) + ;; + + match intparse(sp[0]) + | `Some pid: + xpid = pid + if sp.len == 4 || (sp.len == 5 && sp[4].len > 0) /* we exited with nil */ + st = `Wsuccess + elif sp.len == 5 /* we have a status */ + st = `Wfailure + else /* we have a malformed await message */ + st = `Waiterror + ;; + | `None: + xpid = -1 + st = `Waiterror + ;; + + slfree(sp) + -> (st, xpid) + +} + +const pidhash = {x; -> inthash(x castto(int32))} +const pideq = {a, b; -> a == b}
\ No newline at end of file |