(* Test: more of the Thread interface *) MODULE Main; IMPORT Fmt, Wr, Thread, Stdio; <*FATAL ANY*> TYPE T = Thread.Closure BRANDED "p007 T" OBJECT id: INTEGER; limit: INTEGER := 15; OVERRIDES apply := Task; END; A = MUTEX BRANDED "p007 common" OBJECT first, last, next, limit: INTEGER; done: Thread.Condition; count: INTEGER := 0; METHODS Wait (c: Thread.Condition) := Thread.Wait; END; VAR com: A; stop: Thread.Condition; PROCEDURE Task (self: T) : REFANY RAISES {} = VAR next: T; BEGIN LOOP TRY LOCK com DO WHILE (com.next # self.id) DO com.Wait (com.done); END; Wr.PutText (Stdio.stdout, Fmt.Int (self.id) & " "); DEC (self.limit); IF self.limit <= 0 THEN IF (self.id = com.limit) THEN com.next := 0; ELSE com.first := self.id + 1; com.next := com.first; END; RETURN NIL; ELSIF (self.id = com.last) THEN INC (com.count); Wr.PutText (Stdio.stdout, "\n" & Fmt.Pad (Fmt.Int (com.count) & ": ", 7)); IF (self.id # com.limit) THEN com.last := self.id + 1; next := NEW (T, id := com.last, limit := 15); EVAL Thread.Fork (next); END; com.next := com.first; ELSE com.next := self.id + 1; END; END; FINALLY Thread.Broadcast (com.done); END; END; END Task; VAR t: T; th: Thread.T; BEGIN stop := NEW (Thread.Condition); com := NEW (A, limit := 2000); com.done := NEW (Thread.Condition); com.first := 1; com.next := 1; com.last := 1; t := NEW (T, id := 1, limit := 15); INC (com.count); Wr.PutText (Stdio.stdout, Fmt.Pad (Fmt.Int (com.count) & ": ", 7)); th := Thread.Fork (t); Thread.Broadcast (com.done); LOOP LOCK com DO WHILE (com.next # 0) DO com.Wait (com.done); END; EXIT; END; END; Wr.PutText (Stdio.stdout, "\nDone.\n"); Wr.Close (Stdio.stdout); END Main.