-- SMALL TASK Environment for task queue exercise -- Currently number 5 in the queue module -- OCT 31, 1983 -- Dec 15, revised to inclkude initializations needed in CONSUMER -- this one includes a regular queue package -- REVISED 10-1-84 NO INPUT FOR PERFORMANCE SUITE -- Author Bob Laddaga Package QUEUE_PKG is --a package implementing circular queues for -- CHARACTER items. -- MAX_COUNT is the maximum number of items the queue can hold. MAX_COUNT : constant := 10; type QUEUE is private; function EMPTY_Q ( Q : QUEUE ) return BOOLEAN; -- Returns TRUE if Q is empty, FALSE otherwise. function FULL_Q ( Q : QUEUE ) return BOOLEAN; -- Returns TRUE if QUEUE is full, FALSE otherwise. procedure ENQUEUE ( Q : in out QUEUE; IN_ITEM : in CHARACTER ); -- Adds IN_ITEM to the front of Q. -- Does nothing (just returns) if Q is full. procedure DEQUEUE ( Q : in out QUEUE; OUT_ITEM : out CHARACTER ); -- Removes an item from the rear of Q, returning it in OUT_ITEM. -- Does nothing (just returns) if Q is empty. private -- MAX_SIZE is the upper bound of the array holding the queue. MAX_SIZE : constant := MAX_COUNT - 1; -- MODNUM is the type of the index of the array holding the queue. subtype MODNUM is INTEGER range 0 .. MAX_SIZE; -- COUNTNUM is the type of the counter for items in the array subtype COUNTNUM is INTEGER range 0 .. MAX_COUNT; type Q_ARR is array ( 0 .. MAX_SIZE ) of CHARACTER; type QUEUE is record FRONT : MODNUM := 1; REAR : MODNUM := 0; COUNT : COUNTNUM := 0; ITEM : Q_ARR; end record; end QUEUE_PKG; with QUEUE_PKG, TEXT_IO; use QUEUE_PKG, TEXT_IO; procedure TASK_EXERCISE is NUM_PRODUCERS : INTEGER := 2; task BUFFER is entry IN_CHAR( IN_ITEM : in CHARACTER ); entry OUT_CHAR( OUT_ITEM : out CHARACTER ); entry STOP; end BUFFER; task INPUT_SERVER is entry GET_STRING( STR : in out STRING; LAST : out INTEGER ); entry STOP; end INPUT_SERVER; task FIRST_PRODUCER; task SECOND_PRODUCER; task CONSUMER; task body INPUT_SERVER is begin loop select accept GET_STRING ( STR : in out STRING; LAST : out INTEGER )do PUT( "Type a string of 10 characters: " ); -- GET_LINE( STR, LAST ); STR := "ABCDEFGHIJ"; LAST := 10; end; or accept STOP; exit; or terminate; end select; end loop; end INPUT_SERVER; task body FIRST_PRODUCER is STR1 : STRING ( 1 .. 10 ) := " "; LAST1 : INTEGER; begin -- FIRST_PRODUCER INPUT_SERVER.GET_STRING( STR1, LAST1 ); for I in 1 .. LAST1 loop BUFFER.IN_CHAR( STR1( I ) ); end loop; BUFFER.IN_CHAR( ASCII.EOT ); end FIRST_PRODUCER; task body SECOND_PRODUCER is STR2 : STRING ( 1 .. 10 ) := " "; LAST2 : INTEGER; begin -- SECOND_PRODUCER INPUT_SERVER.GET_STRING( STR2, LAST2 ); for I in 1 .. LAST2 loop BUFFER.IN_CHAR( STR2( I ) ); end loop; BUFFER.IN_CHAR( ASCII.EOT ); end SECOND_PRODUCER; task body CONSUMER is CHAR : CHARACTER := ' '; NUM_ENDED : INTEGER := 0; begin -- CONSUMER loop BUFFER.OUT_CHAR( CHAR ); if CHAR = ASCII.EOT then NUM_ENDED := NUM_ENDED + 1; end if; if NUM_ENDED = NUM_PRODUCERS then exit; else PUT( CHAR ); end if; end loop; INPUT_SERVER.STOP; BUFFER.STOP; end CONSUMER; task body BUFFER is separate; begin -- TASK_EXERCISE null; end TASK_EXERCISE; package body QUEUE_PKG is function MODADD1( I : MODNUM ) return MODNUM is -- the function which takes an integer between 0 and -- MAX_SIZE and returns the integer incremented by 1 -- modulo MAX_SIZE + 1. begin return ( (I + 1) mod MAX_COUNT ); end MODADD1; function EMPTY_Q ( Q : QUEUE ) return BOOLEAN is -- Returns TRUE if the Q is empty FALSE otherwise. begin -- if ( Q.COUNT = 0 ) then put_line ("queue is empty"); -- else put_line ("queue is not empty"); -- end if; return ( Q.COUNT = 0 ); end EMPTY_Q; function FULL_Q ( Q : QUEUE ) return BOOLEAN is -- Returns TRUE if the Q is full FALSE otherwise. begin -- if ( Q.COUNT = MAX_COUNT ) then put_line ("queue is full"); -- else put_line ("queue is not full"); -- end if; return ( Q.COUNT = MAX_COUNT ); end FULL_Q; procedure ENQUEUE ( Q : in out QUEUE; IN_ITEM : in CHARACTER ) is -- Adds IN_ITEM to the front of Q. -- Does nothing (just returns) if Q is full. begin if Q.COUNT = MAX_COUNT then return; end if; Q.REAR := MODADD1( Q.REAR ); Q.ITEM(Q.REAR) := IN_ITEM; Q.COUNT := Q.COUNT + 1; end ENQUEUE; procedure DEQUEUE ( Q : in out QUEUE; OUT_ITEM : out CHARACTER ) is -- Removes an item from the rear of Q, returning it in OUT_ITEM. -- Does nothing (just returns) if Q is empty. begin if Q.COUNT = 0 then return; end if; OUT_ITEM := Q.ITEM( Q.FRONT ); Q.FRONT := MODADD1( Q.FRONT ); Q.COUNT := Q.COUNT - 1; end DEQUEUE; end QUEUE_PKG;