packages feed

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.