packages feed

language-Modula2-0.1: examples/Modula-2_Libraries/PMOS/sources/general/queues.mod

IMPLEMENTATION MODULE Queues;

	(********************************************************)
	(*							*)
	(*		Generic queue module.			*)
	(*							*)
	(*  Programmer:		P. Moylan			*)
	(*  Last edited:	21 February 1995		*)
	(*  Status:		Working.			*)
	(*							*)
	(********************************************************)

FROM Storage1 IMPORT
    (* proc *)	ALLOCATE, DEALLOCATE;

FROM Semaphores IMPORT
    (* type *)	Semaphore,
    (* proc *)	CreateSemaphore, DestroySemaphore, Wait, Signal;

FROM TaskControl IMPORT
    (* type *)	Lock,
    (* proc *)	CreateLock, DestroyLock, Obtain, Release;

(************************************************************************)

TYPE

    (* A QueueLink is a pointer from one queue element to the next.	*)

    QueueLink = POINTER TO QueueElement;

    (* The actual queue element contains a pointer to the next queue	*)
    (* element, and a pointer to the enqueued data.			*)

    QueueElement =  RECORD
			next: QueueLink;
			DataPtr: ADDRESS;
		    END (*RECORD*);

    (* Every queue has a header, which contains pointers to the head	*)
    (* and tail of the queue; an access lock for critical section	*)
    (* protection; and a counting semaphore which keeps track of the	*)
    (* size of the queue.						*)

    QueueHeader =   RECORD
			head, tail: QueueLink;
			access: Lock;
			count: Semaphore;
		    END (*RECORD*);

    (* Finally, a Queue is defined via a pointer to its header.		*)

    Queue = POINTER TO QueueHeader;

(************************************************************************)

PROCEDURE CreateQueue (VAR (*OUT*) Q: Queue);

    (* Creates a new queue, initially empty.	*)

    BEGIN
	NEW (Q);
	WITH Q^ DO
	    head := NIL;  tail := NIL;
	    CreateLock (access);
	    CreateSemaphore (count, 0);
	END (*WITH*);
    END CreateQueue;

(************************************************************************)

PROCEDURE DestroyQueue (Q: Queue);

    (* Destroys queue Q, thus freeing up the space it occupied.  Any	*)
    (* data still on the queue are lost.  After this call, no further	*)
    (* operations should be performed on the queue.			*)

    VAR following: QueueLink;

    BEGIN
	WITH Q^ DO
	    Obtain (access);
	    WHILE head <> NIL DO
		following := head^.next;
		DISPOSE (head);
		head := following;
	    END (*WHILE*);
	    DestroyLock (access);
	    DestroySemaphore (count);
	END (*WITH*);
	DISPOSE (Q);
    END DestroyQueue;

(************************************************************************)

PROCEDURE AddToQueue (Q: Queue;  DataPointer: ADDRESS);

    (* Places a new element at the tail of queue Q.  The caller has an	*)
    (* obligation to ensure that DataPointer^ remains in existence	*)
    (* for as long as it remains on the queue.				*)

    VAR element: QueueLink;

    BEGIN
	NEW (element);
	WITH element^ DO
	    next := NIL;  DataPtr := DataPointer;
	END (*WITH*);
	WITH Q^ DO
	    Obtain (access);
	    IF head = NIL THEN
		head := element;
	    ELSE
		tail^.next := element;
	    END (*IF*);
	    tail := element;
	    Release (access);
	    Signal (count);
	END (*WITH*);
    END AddToQueue;

(************************************************************************)

PROCEDURE TakeFromQueue (Q: Queue): ADDRESS;

    (* Removes and returns a pointer to the datum at the head of the	*)
    (* queue.								*)

    VAR result: ADDRESS;
	second: QueueLink;

    BEGIN
	WITH Q^ DO
	    Wait (count);
	    Obtain (access);
	    second := head^.next;  result := head^.DataPtr;
	    DISPOSE (head);
	    head := second;
	    IF head = NIL THEN
		tail := NIL;
	    END (*IF*);
	    Release (access);
	END (*WITH*);
	RETURN result;
    END TakeFromQueue;

(************************************************************************)

PROCEDURE Empty (Q: Queue): BOOLEAN;

    (* Returns TRUE iff Q is empty.	*)

    VAR result: BOOLEAN;

    BEGIN
	WITH Q^ DO
	    Obtain (access);
	    result := head = NIL;
	    Release (access);
	END (*WITH*);
	RETURN result;
    END Empty;

(************************************************************************)

END Queues.