-- File: QueueIn.mesa - last edit:
-- MAS May 19, 1980 6:21 PM
-- HGM October 15, 1979 8:00 PM

-- Copyright Xerox Corporation 1979, 1980

DIRECTORY
DriverDefs: FROM "DriverDefs" USING [
doDebug, Glitch, freeQueueLock, freeQueueNotEmpty],
PupDefs: FROM "PupDefs", -- EXPORTs
BufferDefs: FROM "BufferDefs" USING [
Buffer, PupBuffer, RppBuffer,
Enqueue, QueueObject, buffersToReserve],
DriverTypes: FROM "DriverTypes";

QueueIn: MONITOR LOCKS DriverDefs.freeQueueLock
IMPORTS DriverDefs, BufferDefs
EXPORTS DriverDefs, PupDefs, BufferDefs
SHARES BufferDefs =
BEGIN OPEN DriverDefs, BufferDefs;

freeQueue: PUBLIC QueueObject;
firstBuffer: PUBLIC Buffer ← NIL; -- debugging flag

FreeQueueNotInitialized: PUBLIC ERROR = CODE;

ReturnFreePupBuffer: PUBLIC PROCEDURE [PupBuffer] = LOOPHOLE[ReturnFreeBuffer];
ReturnFreeRppBuffer: PUBLIC PROCEDURE [RppBuffer] = LOOPHOLE[ReturnFreeBuffer];
ReturnFreeBuffer: PUBLIC ENTRY PROCEDURE [b: Buffer] =
BEGIN
IF doDebug AND firstBuffer=NIL THEN Glitch[FreeQueueNotInitialized];
-- Note: we do some "initialization" of things here since there are several ways to get buffers from the freeQueue.
b.requeueProcedure ← ReturnFreeBuffer;
b.network ← NIL;
Enqueue[@freeQueue,b];
-- This is ugly, but I can see any way to make things work if 2 PROCESSes are waiting for clumps without it.
BROADCAST freeQueueNotEmpty;
END;

BuffersLeft: PUBLIC PROCEDURE RETURNS [left: CARDINAL] =
BEGIN
IF doDebug AND firstBuffer=NIL THEN Glitch[FreeQueueNotInitialized];
left ← freeQueue.length;
left ← (IF left>buffersToReserve THEN left-buffersToReserve ELSE 0);
END;

-- initialization
END. -- QueueIn