(* acct.sml *) (* bank accounts with non-negative integer balances *) structure Acct :> ACCT = struct open CML (* requests Inc n is an incrementation request: increment an account's balance by n Dec(n, approveEv) is a decrementation request: decrement an account's balance by n; the server synchronizes on approveEv when it is ready to approve the request *) datatype req = Inc of int | Dec of int * unit event (* a bank account is a request channel *) type acct = req chan (* decrementation request queue *) type dec_queue = (int * unit event)Fifo.fifo (* val server : req chan * int * dec_queue -> 'a *) fun server(ch, bal, que) = if case Fifo.peek que of NONE => false | SOME(n, _) => n <= bal then let val (que, (n, approveEv)) = Fifo.dequeue que in sync approveEv; server(ch, bal - n, que) end else case recv ch of Inc n => server(ch, bal + n, que) | Dec dec => server(ch, bal, Fifo.enqueue(que, dec)) (* val make : unit -> acct *) fun make() = let val ch = channel() : req chan in spawn(fn () => server(ch, 0, Fifo.empty)); ch end exception NonPositive (* val incEvt : acct * int -> unit event *) fun incEvt(ch, n) = if n <= 0 then raise NonPositive else sendEvt(ch, Inc n) (* val decEvt : acct * int -> unit event *) fun decEvt(ch, n) = if n <= 0 then raise NonPositive else guard (fn () => let val replyCh : unit chan = channel() val approveEv : unit event = sendEvt(replyCh, ()) in wrap(sendEvt(ch, Dec(n, approveEv)), fn () => (print "waiting for reply\n"; recv replyCh)) end) end;