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

  1. IMPLEMENTATION MODULE CircularBuffers;
  2.  
  3.         (********************************************************)
  4.         (*                                                      *)
  5.         (*      Circular Buffers for passing character data     *)
  6.         (*      between a pair of tasks.                        *)
  7.         (*                                                      *)
  8.         (*      Author:         P. Moylan                       *)
  9.         (*      Last edited:    18 October 1996                 *)
  10.         (*      Status:         Working on XDS version          *)
  11.         (*                                                      *)
  12.         (********************************************************)
  13.  
  14. FROM Storage IMPORT
  15.     (* proc *)  ALLOCATE;
  16.  
  17. FROM Timer IMPORT
  18.     (* proc *)  TimedWait;
  19.  
  20. FROM Semaphores IMPORT
  21.     (* type *)  Semaphore,
  22.     (* proc *)  CreateSemaphore, Wait, Signal;
  23.  
  24. FROM TaskControl IMPORT
  25.     (* type *)  Lock,
  26.     (* proc *)  CreateLock, Obtain, Release;
  27.  
  28. (************************************************************************)
  29.  
  30. CONST MaxChars = 65536;
  31.  
  32. TYPE
  33.     BufferTemplate = RECORD
  34.                         SlotAvailable, DataPresent: Semaphore;
  35.                         lastlocation: CARDINAL;
  36.                         mutex: Lock;
  37.                         GetPlace, PutPlace: CARDINAL;
  38.                         data: ARRAY [0..MaxChars-1] OF CHAR
  39.                      END;
  40.  
  41.     CircularBuffer = POINTER TO BufferTemplate;
  42.  
  43. (************************************************************************)
  44.  
  45. PROCEDURE CreateBuffer (VAR (*OUT*) B: CircularBuffer;  size: CARDINAL);
  46.  
  47.     (* Allocates space for a circular buffer, and initializes it.  The  *)
  48.     (* caller specifies how many characters the buffer will hold.       *)
  49.  
  50.     BEGIN
  51.         ALLOCATE (B, SIZE(BufferTemplate) - SIZE(CHAR) * (MaxChars - size));
  52.         WITH B^ DO
  53.             lastlocation := size - 1;
  54.             CreateSemaphore (SlotAvailable, size);
  55.             CreateSemaphore (DataPresent, 0);
  56.             CreateLock (mutex);
  57.             GetPlace := 0;  PutPlace := 0;
  58.         END (*WITH*);
  59.     END CreateBuffer;
  60.  
  61. (************************************************************************)
  62.  
  63. PROCEDURE PutBuffer (B: CircularBuffer; item: CHAR);
  64.  
  65.     (* Puts item into the circular buffer, waiting for space available  *)
  66.     (* if necessary.                                                    *)
  67.  
  68.     BEGIN
  69.         WITH B^ DO
  70.             Wait (SlotAvailable);
  71.             data[PutPlace] := item;
  72.             IF PutPlace = lastlocation THEN PutPlace := 0
  73.             ELSE INC (PutPlace);
  74.             END (*IF*);
  75.             Signal (DataPresent);
  76.         END (*WITH*);
  77.     END PutBuffer;
  78.  
  79. (************************************************************************)
  80.  
  81. PROCEDURE PutBufferImpatient (B: CircularBuffer;  item: CHAR;
  82.                                                 TimeLimit: CARDINAL);
  83.  
  84.     (* Like PutBuffer, but waits no longer than TimeLimit milliseconds  *)
  85.     (* for a buffer slot to become available.  If the time limit        *)
  86.     (* expires, the oldest item in the buffer is overwritten by the     *)
  87.     (* new data.                                                        *)
  88.  
  89.     VAR TimedOut: BOOLEAN;
  90.  
  91.     BEGIN
  92.         WITH B^ DO
  93.             TimedWait (SlotAvailable, TimeLimit, TimedOut);
  94.             IF TimedOut THEN
  95.                 Obtain (mutex);
  96.                 IF GetPlace = lastlocation THEN GetPlace := 0
  97.                 ELSE INC (GetPlace);
  98.                 END (*IF*);
  99.                 Release (mutex);
  100.             END (*IF*);
  101.             data[PutPlace] := item;
  102.             IF PutPlace = lastlocation THEN PutPlace := 0
  103.             ELSE INC (PutPlace);
  104.             END (*IF*);
  105.             IF NOT TimedOut THEN
  106.                 Signal (DataPresent);
  107.             END (*IF*);
  108.         END (*WITH*);
  109.     END PutBufferImpatient;
  110.  
  111. (************************************************************************)
  112.  
  113. PROCEDURE GetBuffer (B: CircularBuffer) : CHAR;
  114.  
  115.     (* Gets one character from the circular buffer, waiting when        *)
  116.     (* necessary for a character to become available.                   *)
  117.  
  118.     VAR result: CHAR;
  119.  
  120.     BEGIN
  121.         WITH B^ DO
  122.             Wait (DataPresent);
  123.             Obtain (mutex);
  124.             result := data[GetPlace];
  125.             IF GetPlace = lastlocation THEN GetPlace := 0
  126.             ELSE INC (GetPlace);
  127.             END (*IF*);
  128.             Release (mutex);
  129.             Signal (SlotAvailable);
  130.         END (*WITH*);
  131.         RETURN result;
  132.     END GetBuffer;
  133.  
  134. (************************************************************************)
  135.  
  136. PROCEDURE BufferEmpty (B: CircularBuffer): BOOLEAN;
  137.  
  138.     (* Returns TRUE iff the buffer is empty. *)
  139.  
  140.     VAR TimedOut: BOOLEAN;
  141.  
  142.     BEGIN
  143.         WITH B^ DO
  144.             TimedWait (DataPresent, 0, TimedOut);
  145.             IF TimedOut THEN RETURN TRUE;
  146.             ELSE
  147.                 Signal (DataPresent);
  148.                 RETURN FALSE;
  149.             END (*IF*);
  150.         END (*WITH*);
  151.     END BufferEmpty;
  152.  
  153. (************************************************************************)
  154.  
  155. END CircularBuffers.
  156.  
  157.