language-Modula2-0.1: examples/Modula-2_Libraries/PMOS/sources/tests/sematest.mod
MODULE SemaTest;
(********************************************************)
(* *)
(* Test program to check that the semaphore *)
(* operations work. *)
(* *)
(* Programmer: P. Moylan *)
(* Last edited: 9 February 1995 *)
(* *)
(* Description: Runs a pair of tasks in a *)
(* simple producer/consumer relationship. *)
(* *)
(* Status: *)
(* Working, except for a bug in *)
(* tracing: attempting to trace kernel *)
(* causes infinite recursion. For now *)
(* kernel tracing has been removed, but *)
(* given the intended use of this program *)
(* we should find a mechanism for kernel *)
(* tracing. *)
(* *)
(********************************************************)
FROM Windows IMPORT
(* type *) Window, Colour, FrameType, DividerType,
(* proc *) OpenWindow, CloseWindow, WriteString, WriteLn, Write,
PressAnyKey, ReadChar;
FROM Trace IMPORT
(* proc *) TraceOn;
FROM Semaphores IMPORT
(* type *) Semaphore,
(* proc *) CreateSemaphore, Wait, Signal;
FROM TaskControl IMPORT
(* proc *) CreateTask, TaskExit;
FROM CircularBuffers IMPORT
(* type *) CircularBuffer,
(* proc *) CreateBuffer, PutBuffer, GetBuffer;
(************************************************************************)
CONST Esc = CHR(01BH);
VAR
(* The consumer and producer tasks will communicate through a *)
(* circular buffer called "pipe". *)
pipe: CircularBuffer;
(* logwindow is a screen window used for status messages. *)
logwindow: Window;
(* The "finished" semaphore is needed so the main task will know *)
(* when the consumer and producer tasks have both exited. *)
finished: Semaphore;
(************************************************************************)
(* THE PRODUCER AND CONSUMER TASKS *)
(************************************************************************)
PROCEDURE Producer;
(* The producer task. Takes input from the keyboard, sends it to *)
(* the intertask buffer where it will be picked up by the consumer *)
(* task. Exits when a second Esc key is received (the first is *)
(* sent to the consumer task). *)
VAR datum: CHAR; EscSent: BOOLEAN;
pwindow: Window;
BEGIN
OpenWindow (pwindow, red, green, 4, 11, 0, 39, simpleframe, nodivider);
WriteString (pwindow, "Starting producer task.");
WriteLn (pwindow);
EscSent := FALSE;
LOOP
ReadChar (pwindow, datum);
IF datum = Esc THEN
IF EscSent THEN EXIT(*LOOP*) END (*IF*);
EscSent := TRUE;
END (*IF*);
PutBuffer (pipe, datum);
END (*LOOP*);
WriteString (pwindow, "Producer task is now terminating.");
WriteLn (pwindow);
CloseWindow (pwindow);
Signal (finished);
TaskExit;
END Producer;
(************************************************************************)
PROCEDURE Consumer;
(* The consumer task. Takes input from the intertask buffer and *)
(* prints it, changing lower case letters to upper case. *)
(* Exits when an Esc character has been received. *)
VAR datum: CHAR;
cwindow: Window;
BEGIN
OpenWindow (cwindow, blue, cyan, 7,14, 30,69, simpleframe, nodivider);
WriteString (cwindow, "Starting consumer task.");
WriteLn (cwindow);
LOOP
datum := GetBuffer(pipe);
IF (datum >= 'a') AND (datum <= 'z') THEN
datum := CHR (ORD(datum)-ORD('a')+ORD('A'))
END (*IF*);
IF datum = Esc THEN EXIT(*LOOP*) END(*IF*);
Write (cwindow, datum);
END (*LOOP*);
WriteLn (cwindow);
WriteString (cwindow, "Consumer task is now terminating.");
WriteLn (cwindow);
CloseWindow (cwindow);
Signal (finished);
TaskExit;
END Consumer;
(************************************************************************)
(* THE TEST PROCEDURE *)
(************************************************************************)
PROCEDURE RunTheTest;
CONST ProducerPriority = 1; ConsumerPriority = 1;
VAR taskcount: CARDINAL;
BEGIN
CreateBuffer (pipe, 8);
CreateSemaphore (finished, 0);
taskcount := 0;
CreateTask (Consumer, ConsumerPriority, "Consumer");
INC (taskcount);
WriteString (logwindow, "Have created consumer task.");
WriteLn (logwindow);
CreateTask (Producer, ProducerPriority, "Producer");
INC (taskcount);
WriteString (logwindow, "Have created producer task.");
WriteLn (logwindow);
WHILE taskcount > 0 DO
Wait (finished); DEC(taskcount);
END (*WHILE*);
WriteString (logwindow,
"All tasks terminated - back in RunTheTest.");
WriteLn (logwindow);
END RunTheTest;
(************************************************************************)
(* MAIN PROGRAM *)
(************************************************************************)
BEGIN
(*TraceOn (10, 24, 0, 79, 50);*)
OpenWindow (logwindow, white, black, 0, 3, 0, 49,
noframe, nodivider);
WriteString (logwindow, "Test of semaphore operations.");
WriteLn (logwindow);
RunTheTest;
WriteString (logwindow, "End of test.");
PressAnyKey (logwindow);
CloseWindow (logwindow);
END SemaTest.