home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pmos2002.zip / SRC / QUEUES.MOD < prev    next >
Text File  |  1996-10-17  |  6KB  |  204 lines

  1. IMPLEMENTATION MODULE Queues;
  2.  
  3.         (********************************************************)
  4.         (*                                                      *)
  5.         (*              Generic queue module.                   *)
  6.         (*                                                      *)
  7.         (*  Programmer:         P. Moylan                       *)
  8.         (*  Last edited:        17 September 1996               *)
  9.         (*  Status:             Working.                        *)
  10.         (*                                                      *)
  11.         (********************************************************)
  12.  
  13. FROM SYSTEM IMPORT
  14.     (* type *)  ADDRESS;
  15.  
  16. FROM Storage IMPORT
  17.     (* proc *)  ALLOCATE, DEALLOCATE;
  18.  
  19. FROM Semaphores IMPORT
  20.     (* type *)  Semaphore,
  21.     (* proc *)  CreateSemaphore, DestroySemaphore, Wait, Signal;
  22.  
  23. FROM Timer IMPORT
  24.     (* proc *)  TimedWait;
  25.  
  26. FROM TaskControl IMPORT
  27.     (* type *)  Lock,
  28.     (* proc *)  CreateLock, DestroyLock, Obtain, Release;
  29.  
  30. (************************************************************************)
  31.  
  32. TYPE
  33.  
  34.     (* A QueueLink is a pointer from one queue element to the next.     *)
  35.  
  36.     QueueLink = POINTER TO QueueElement;
  37.  
  38.     (* The actual queue element contains a pointer to the next queue    *)
  39.     (* element, and a pointer to the enqueued data.                     *)
  40.  
  41.     QueueElement =  RECORD
  42.                         next: QueueLink;
  43.                         DataPtr: ADDRESS;
  44.                     END (*RECORD*);
  45.  
  46.     (* Every queue has a header, which contains pointers to the head    *)
  47.     (* and tail of the queue; an access lock for critical section       *)
  48.     (* protection; and a counting semaphore which keeps track of the    *)
  49.     (* size of the queue.                                               *)
  50.  
  51.     QueueHeader =   RECORD
  52.                         head, tail: QueueLink;
  53.                         access: Lock;
  54.                         count: Semaphore;
  55.                     END (*RECORD*);
  56.  
  57.     (* Finally, a Queue is defined via a pointer to its header.         *)
  58.  
  59.     Queue = POINTER TO QueueHeader;
  60.  
  61. (************************************************************************)
  62.  
  63. PROCEDURE CreateQueue (VAR (*OUT*) Q: Queue);
  64.  
  65.     (* Creates a new queue, initially empty.    *)
  66.  
  67.     BEGIN
  68.         NEW (Q);
  69.         WITH Q^ DO
  70.             head := NIL;  tail := NIL;
  71.             CreateLock (access);
  72.             CreateSemaphore (count, 0);
  73.         END (*WITH*);
  74.     END CreateQueue;
  75.  
  76. (************************************************************************)
  77.  
  78. PROCEDURE DestroyQueue (Q: Queue);
  79.  
  80.     (* Destroys queue Q, thus freeing up the space it occupied.  Any    *)
  81.     (* data still on the queue are lost.  After this call, no further   *)
  82.     (* operations should be performed on the queue.                     *)
  83.  
  84.     VAR following: QueueLink;
  85.  
  86.     BEGIN
  87.         WITH Q^ DO
  88.             Obtain (access);
  89.             WHILE head <> NIL DO
  90.                 following := head^.next;
  91.                 DISPOSE (head);
  92.                 head := following;
  93.             END (*WHILE*);
  94.             DestroyLock (access);
  95.             DestroySemaphore (count);
  96.         END (*WITH*);
  97.         DISPOSE (Q);
  98.     END DestroyQueue;
  99.  
  100. (************************************************************************)
  101.  
  102. PROCEDURE AddToQueue (Q: Queue;  DataPointer: ADDRESS);
  103.  
  104.     (* Places a new element at the tail of queue Q.  The caller has an  *)
  105.     (* obligation to ensure that DataPointer^ remains in existence      *)
  106.     (* for as long as it remains on the queue.                          *)
  107.  
  108.     VAR element: QueueLink;
  109.  
  110.     BEGIN
  111.         NEW (element);
  112.         WITH element^ DO
  113.             next := NIL;  DataPtr := DataPointer;
  114.         END (*WITH*);
  115.         WITH Q^ DO
  116.             Obtain (access);
  117.             IF head = NIL THEN
  118.                 head := element;
  119.             ELSE
  120.                 tail^.next := element;
  121.             END (*IF*);
  122.             tail := element;
  123.             Release (access);
  124.             Signal (count);
  125.         END (*WITH*);
  126.     END AddToQueue;
  127.  
  128. (************************************************************************)
  129.  
  130. PROCEDURE TakeFromQueue (Q: Queue): ADDRESS;
  131.  
  132.     (* Removes and returns a pointer to the datum at the head of the    *)
  133.     (* queue.                                                           *)
  134.  
  135.     VAR result: ADDRESS;
  136.         second: QueueLink;
  137.  
  138.     BEGIN
  139.         WITH Q^ DO
  140.             Wait (count);
  141.             Obtain (access);
  142.             second := head^.next;  result := head^.DataPtr;
  143.             DISPOSE (head);
  144.             head := second;
  145.             IF head = NIL THEN
  146.                 tail := NIL;
  147.             END (*IF*);
  148.             Release (access);
  149.         END (*WITH*);
  150.         RETURN result;
  151.     END TakeFromQueue;
  152.  
  153. (************************************************************************)
  154.  
  155. PROCEDURE TakeFromQueueTimed (Q: Queue;  TimeLimit: CARDINAL): ADDRESS;
  156.  
  157.     (* Like TakeFromQueue, but waits no longer than TimeLimit           *)
  158.     (* milliseconds.  Returns NIL if the time limit expires.  Choose    *)
  159.     (* TimeLimit=0 for a non-blocking check of the queue.               *)
  160.  
  161.     VAR result: ADDRESS;  TimedOut: BOOLEAN;
  162.         second: QueueLink;
  163.  
  164.     BEGIN
  165.         WITH Q^ DO
  166.             TimedWait (count, TimeLimit, TimedOut);
  167.             IF TimedOut THEN
  168.                 result := NIL;
  169.             ELSE
  170.                 Obtain (access);
  171.                 second := head^.next;  result := head^.DataPtr;
  172.                 DISPOSE (head);
  173.                 head := second;
  174.                 IF head = NIL THEN
  175.                     tail := NIL;
  176.                 END (*IF*);
  177.                 Release (access);
  178.             END (*IF*);
  179.         END (*WITH*);
  180.         RETURN result;
  181.     END TakeFromQueueTimed;
  182.  
  183. (************************************************************************)
  184.  
  185. PROCEDURE Empty (Q: Queue): BOOLEAN;
  186.  
  187.     (* Returns TRUE iff Q is empty.     *)
  188.  
  189.     VAR result: BOOLEAN;
  190.  
  191.     BEGIN
  192.         WITH Q^ DO
  193.             Obtain (access);
  194.             result := head = NIL;
  195.             Release (access);
  196.         END (*WITH*);
  197.         RETURN result;
  198.     END Empty;
  199.  
  200. (************************************************************************)
  201.  
  202. END Queues.
  203.  
  204.