(* 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 sleep : int -> unit *) fun sleep n = sync(timeOutEvt(Time.fromSeconds n)) (* val producer : string Buffer.buffer * string Buffer.buffer * string * int -> 'a *) fun producer(buf1, buf2, name, tim) = let val add1Evt : string -> unit event = Buffer.addEvt buf1 val add2Evt : string -> unit event = Buffer.addEvt buf2 (* val loop : int -> 'a *) fun loop n = (select [add1Evt(name ^ ":" ^ Int.toString n), add2Evt(name ^ ":" ^ Int.toString n)]; sleep tim; loop(n + 1)) in loop 0 end (* val length : string Buffer.buffer * int * int * int * int -> 'a *) fun length(buf, bufNum, first, second, tim) = let val lenEvt : int event = Buffer.lenEvt buf val newMaxLenEvt : int -> bool event = Buffer.newMaxLenEvt buf (* val loop : bool -> 'a *) fun loop mode = select [wrap(lenEvt, fn n => (print("current length of buf" ^ Int.toString bufNum ^ ": " ^ Int.toString n ^ "\n"); sleep tim; loop mode)), let val newLen = if mode then first else second in wrap(newMaxLenEvt newLen, fn b => (print("attempt to set new max length of buf" ^ Int.toString bufNum ^ " to " ^ Int.toString newLen ^ ": " ^ (if b then "success" else "failure") ^ "\n"); sleep tim; loop(if b then not mode else mode))) end] in loop true end (* val main : unit -> unit *) fun main() = let val buf1 : string Buffer.buffer = Buffer.make 10 val buf2 : string Buffer.buffer = Buffer.make 20 val del1Evt : string event = Buffer.delEvt buf1 val del2Evt : string event = Buffer.delEvt buf2 (* val loop : unit -> unit *) fun loop() = case TextIO.inputLine TextIO.stdIn of SOME "\n" => select [wrap(del1Evt, fn s => (print("from buf1: " ^ s ^ "\n"); loop())), wrap(del2Evt, fn s => (print("from buf2: " ^ s ^ "\n"); loop()))] | _ => RunCML.shutdown OS.Process.success in spawn(fn () => producer(buf1, buf2, "first", 1)); spawn(fn () => producer(buf1, buf2, "second", 2)); spawn(fn () => producer(buf1, buf2, "third", 3)); spawn(fn () => length(buf1, 1, 5, 15, 5)); spawn(fn () => length(buf2, 2, 5, 15, 10)); loop() end (* val doit : unit -> OS.Process.status the second parameter to RunCML.doit is the scheduling time slice; NONE means the default slice of 20 milliseconds *) fun doit() = RunCML.doit(main, NONE) end;