ref: fc4fca0fa6c64a0fbe6fbb5c8faf1e5640b784ea
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(inthash, inteq)
}
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)
}