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