(* 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 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)); 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;