-- XQueueImpl.mesa
-- Created by Jeff Weinstein on 30-Apr-87 23:44:17

DIRECTORY
  Heap,
  XQueue;
  
XQueueImpl:PROGRAM IMPORTS Heap EXPORTS XQueue =
  BEGIN
  
  zone:UNCOUNTED ZONE;
  
  EnQueue:PUBLIC PROCEDURE[q:XQueue.QueuePtr, data:XQueue.Data, size:LONG CARDINAL ← 0 ] =
    BEGIN
    rec:XQueue.RecPtr ← NewRec[];
    rec.data ← data;
    rec.size ← size;
    IF q.head = NIL THEN
      BEGIN
      q.head ← rec;
      q.tail ← rec;
      END
    ELSE
      BEGIN
      rec.prev ← q.tail;
      q.tail.next ← rec;
      q.tail ← rec;
      END;
    q.count ← q.count + 1;
    END;
    
  DeQueue:PUBLIC PROCEDURE [q:XQueue.QueuePtr] RETURNS [data:XQueue.Data, size:LONG CARDINAL] =
    BEGIN
    rec:XQueue.RecPtr;
    SELECT q.head FROM
--      = NIL		=> RETURN WITH ERROR QueueEmpty;
      = NIL		=> RETURN[data:NIL, size:0];
      = q.tail		=> BEGIN
                             rec ← q.head;
			     size ← rec.size;
      			     data ← rec.data;
			     q.head ← NIL;
			     q.tail ← NIL;
			     q.count ← 0;
			   END;
      ENDCASE		=> BEGIN
                             rec ← q.head;
      			     data ← rec.data;
			     size ← rec.size;
			     q.head ← rec.next;
			     q.head.prev ← NIL;
			     q.count ← q.count - 1;
			   END;
    FreeRec[@rec];
			   
    END;
    
  NewRec:PROCEDURE RETURNS[rec:XQueue.RecPtr] =
    BEGIN
      rec ← zone.NEW[XQueue.Rec ← [NIL,0,NIL,NIL]];
    END;
    
  FreeRec:PROCEDURE[recPtr:LONG POINTER TO XQueue.RecPtr] =
    BEGIN
      zone.FREE[recPtr];
    END;
    
  NewQueue:PUBLIC PROCEDURE RETURNS[q:XQueue.QueuePtr] =
    BEGIN
      q ← zone.NEW[XQueue.Queue ← [0,NIL,NIL]];
    END;
    
  FreeQueue:PUBLIC PROCEDURE[qPtr:LONG POINTER TO XQueue.QueuePtr] =
    BEGIN
      zone.FREE[qPtr];
    END;
  
  QueueCount:PUBLIC PROCEDURE[q:XQueue.QueuePtr] RETURNS [count:CARDINAL]=
    BEGIN
      count ← q.count;
    END;
    
  zone ← Heap.Create[initial:64];
  
  END...