(* 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 swapCh : string SwapChannel.swap_chan = SwapChannel.swapChannel() (* val swapStrings : string -> string *) fun swapStrings s = sync(SwapChannel.swapEvt(swapCh, s)) (* val loop : string * string * int -> unit *) fun loop(name, s, 0) = print(name ^ ":" ^ s ^ "\n") | loop(name, s, n) = (print(name ^ ":" ^ s ^ "\n"); loop(name, swapStrings s, n - 1)) (* val child : string * int -> thread_id *) fun child(name, n) = spawn(fn () => loop(name, name, n)) val n = 5 val first : thread_id = child("first", n) val second : thread_id = child("second", n) val third : thread_id = child("third", n) val fourth : thread_id = child("fourth", n) (* val wait : thread_id -> unit *) fun wait threadId = sync(joinEvt threadId) in (* one of the following waits may result in deadlock, when the thread that is waited for is blocked waiting to exchange a string, but none of the other threads want to exchange strings; in this case doit (see below) will returns OS.Process.failure (1) *) wait first; wait second; wait third; wait fourth; RunCML.shutdown OS.Process.success end (* val doit : unit -> OS.Process.status *) fun doit() = RunCML.doit(main, NONE) end;