ref: 8ecdf73fad606722a6f2c05f53ad619c21bf84de
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"
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}