use std use sys use thread use "types" pkg event = generic wait : (h : hub(@ev)# -> @ev#) generic chain : (m : hub(@mev)#, s : hub(@sev)#, cvt : (e : @sev -> @mev) -> void) generic add : (h : hub(@ev)#, fn : (-> @ev) -> void) generic addfd : (h : hub(@ev)#, fd : std.fd, fn : (fd : std.fd -> @ev) -> void) ;; generic wait = {hub var p, r thread.mtxlock(&hub.qmtx) /* find tag for rendezvous */ for evp : [hub.refrp, hub.mousep, hub.kbdp][:] if evp != (0 : void#) p = evp goto found ;; ;; /* if we couldn't find a tag, enqueue ourselves */ p = (hub : void#) for qp : [&hub.refrp, &hub.mousep, &hub.kbdp][:] qp# = p ;; :found thread.mtxunlock(&hub.qmtx) r = (-1 : void#) while r == (-1 : void#) r = sys.rendezvous(p, (0 : void#)) ;; /* now dequeue */ thread.mtxlock(&hub.qmtx) for qp : [&hub.refrp, &hub.mousep, &hub.kbdp][:] if qp# == (hub : void#) qp# = (0 : void#) ;; ;; thread.mtxunlock(&hub.qmtx) -> (r : @ev#) } const send = {hub, qp, evp var p, r thread.mtxlock(&hub.qmtx) if qp# == (0 : void#) /* nobody is queued; we enquue ourselves */ p = (qp : void#) qp# = p else /* somebody is waiting, use their tag */ p = qp# qp# = (0 : void#) ;; thread.mtxunlock(&hub.qmtx) r = (-1 : void#) while r == (-1 : void#) r = sys.rendezvous(p, (evp : void#)) ;; /* now dequeue */ thread.mtxlock(&hub.qmtx) if qp# == (qp : void#) qp# = (0 : void#) ;; thread.mtxunlock(&hub.qmtx) }