ref: 7b5b914cf702375f8f532c2fe43c04d6eacd1fd6
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()
}
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)
}