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