(* main.sml *) (* main processing *) structure Main :> MAIN = struct open CML (* val print : string -> unit we must mention TextIO somewhere in our program, in order to get the correct version of print *) val print = TextIO.print (* val main : unit -> unit *) fun main() = let val acct1 : Acct.acct = Acct.make() val acct2 : Acct.acct = Acct.make() (* val wait : thread_id -> unit *) fun wait tId = sync(joinEvt tId) (* val sleep : int -> unit *) fun sleep n = sync(timeOutEvt(Time.fromSeconds n)) (* val incLoop : string * int * int -> 'a *) fun incLoop(name, amount, slp) = select[wrap(Acct.incEvt(acct1, amount), fn () => (* context-switch possible *) (print(name ^ " added " ^ Int.toString amount ^ " to account 1\n"); sleep slp; incLoop(name, amount, slp))), wrap(Acct.incEvt(acct2, amount), fn () => (* context-switch possible *) (print(name ^ " added " ^ Int.toString amount ^ " to account 2\n"); sleep slp; incLoop(name, amount, slp)))] (* val incChild : string * int * int -> thread_id *) fun incChild(name, amount, slp) = spawn(fn () => incLoop(name, amount, slp)) (* decLoop : string * int * int -> 'a *) fun decLoop(name, amount, slp) = select[wrap(Acct.decEvt(acct1, amount), fn () => (* context-switch possible *) (print(name ^ " decremented " ^ Int.toString amount ^ " from account 1\n"); sleep slp; decLoop(name, amount, slp))), wrap(Acct.decEvt(acct2, amount), fn () => (* context-switch possible *) (print(name ^ " decremented " ^ Int.toString amount ^ " from account 2\n"); sleep slp; decLoop(name, amount, slp)))] (* val decChild : string * int * int -> thread_id *) fun decChild(name, amount, slp) = spawn(fn () => decLoop(name, amount, slp)) val inc1 : thread_id = incChild("inc1", 1, 2) val inc2 : thread_id = incChild("inc2", 15, 6) val dec1 : thread_id = decChild("dec1", 5, 3) val dec2 : thread_id = decChild("dec2", 7, 2) in wait inc1 (* this will never happen *) end (* val doit : unit -> OS.Process.status *) fun doit() = RunCML.doit(main, NONE) end;