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