home *** CD-ROM | disk | FTP | other *** search
/ RBBS in a Box Volume 1 #2 / RBBS_vol1_no2.iso / add2 / queue.cq / QUEUE.C
Text File  |  1989-05-13  |  5KB  |  216 lines

  1. /* FIFO queue package 
  2.  (W) Copywrong 1980 Scott W. Layson
  3.  
  4. These cute little routines implement First In, First Out queues.  There
  5. are complete sets of routines provided: one to handle integer-sized
  6. (2-byte) objects, and the other to handle byte-sized things.
  7.  
  8. The routines are good for applications such as I/O buffering in programs
  9. that do several things at once.  For example, consider the following
  10. program fragment (remember that all this text is one big comment!):
  11.  
  12. #define KBD_Q_SIZE 40
  13.  
  14. struct cqueue {
  15.     char *cruft[4], space[KBD_Q_SIZE];
  16.     } kbd_q;
  17.  
  18. / * This program eats command characters and does something hairy with them * /
  19.  
  20. main()
  21. {
  22.     <... assorted declarations ...>
  23.     CQInit (&kbd_q, KBD_Q_SIZE);
  24.     while (1) do
  25.       {    cmd = get_qd_char();
  26.         hairily_process (cmd);
  27.       }
  28. }
  29.  
  30. / * Return a character off the queue if there are any, otherwise wait
  31.    for one to be typed * /
  32.  
  33. get_qd_char()
  34. {
  35.     if (!CQEmpty(&kbd_q)
  36.         return CQGrab(&kbd_q);
  37.         else return getchar();
  38. }
  39.  
  40. / * If a character has been typed, queue it * /
  41.  
  42. kbd_check()
  43. {
  44.     if (kbhit())
  45.         CQShove (getchar(), &kbd_q);
  46. }
  47.     
  48.  
  49. Careful scattering of calls to kbd_check throughout hairily_process()
  50. will prevent keyboard characters from being missed no matter how far
  51. the user types ahead (up to the KBD_Q_SIZE, of course).
  52.  
  53. Small misfeature: the queue will actually hold one fewer object than
  54. the size allocated for it.  E.g., the above kbd_q will hold
  55. (KBD_Q_SIZE - 1) characters.  This usually doesn't matter, as usual
  56. practice is just to make a queue much larger than it really has to be
  57. anyway.
  58.  
  59. ************** End of comments **********************************/
  60.  
  61.  
  62. struct queue {
  63.     int *head, *tail, *top, *bottom, space;
  64.  };
  65.  
  66.  
  67. /*  Initialization routine (must be called before any operation is done
  68.     on the queue) */
  69.  
  70. QInit(queue_p,size)
  71. struct queue *queue_p;
  72. int size;
  73. {
  74.     queue_p->head = queue_p->tail = queue_p->top = &(queue_p->space);
  75.     queue_p->bottom = queue_p->top +size -1;
  76. }
  77.  
  78.  
  79. /* Routine to grab something off the head of a queue
  80.    Does no error checking!  Be careful of underflow! */
  81.  
  82. QGrab(queue_p)
  83. struct queue *queue_p;
  84. {
  85.     return ((queue_p->head >= queue_p->bottom) ?
  86.         *(queue_p->head = queue_p->top) :
  87.          *++(queue_p->head));
  88. }
  89.  
  90.  
  91. /* Routine to shove something onto the tail of a queue
  92.    Does no error checking! BE careful of underflow! */
  93.  
  94. QShove(x,queue_p)
  95. struct queue *queue_p;
  96. int x;
  97. {
  98.     *((queue_p->tail >= queue_p->bottom) ?
  99.          (queue_p->tail = queue_p->top) :
  100.          ++(queue_p->tail)) = x;
  101. }
  102.  
  103.  
  104. /* Emptiness predicate */
  105.  
  106. QEmpty(queue_p)
  107. struct queue *queue_p;
  108. {
  109.     return (queue_p->head == queue_p->tail);
  110. }
  111.  
  112.  
  113. /* Fullness predicate */
  114.  
  115. QFull(queue_p)
  116. struct queue *queue_p;
  117. {
  118.     return((queue_p->tail+1 == queue_p->head) ||
  119.         (queue_p->tail == queue_p->bottom &&
  120.          queue_p->head == queue_p->top));
  121. }
  122.  
  123.  
  124. /* Peek at head of queue without disturbing it */
  125.  
  126. QPeek(queue_p)
  127. struct queue *queue_p;
  128. {
  129.     return (  (queue_p->head == queue_p->bottom) ?
  130.             *queue_p->top :
  131.             *(queue_p->head + 1) );
  132. }
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139. /* Here is the same repertoire of routines, but set up for
  140.    characters instead of integers:
  141. */
  142.  
  143.  
  144. struct cqueue {
  145.     char *chead, *ctail, *ctop, *cbottom, cspace;
  146.  };
  147.  
  148.  
  149. /*  Initialization routine (must be called before any operation done
  150.     on the queue) */
  151.  
  152. CQInit(queue_p,size)
  153. struct cqueue *queue_p;
  154. int size;
  155. {
  156.     queue_p->chead = queue_p->ctail = queue_p->ctop = &(queue_p->cspace);
  157.     queue_p->cbottom = queue_p->ctop +size -1;
  158. }
  159.  
  160.  
  161. /* Routine to grab something off the head of a queue
  162. Does no error checking!  Be careful of underflow! */
  163.  
  164. CQGrab(queue_p)
  165. struct cqueue *queue_p;
  166. {
  167.     return ((queue_p->chead >= queue_p->cbottom) ?
  168.         *(queue_p->chead = queue_p->ctop) :
  169.          *++(queue_p->chead));
  170. }
  171.  
  172.  
  173. /* Routine to shove something onto the tail of a queue
  174.    Does no error checking!  Be careful of overflow! */
  175.  
  176. CQShove(x,queue_p)
  177. struct cqueue *queue_p;
  178. int x;
  179. {
  180.     *((queue_p->ctail >= queue_p->cbottom) ?
  181.          (queue_p->ctail = queue_p->ctop) :
  182.          ++(queue_p->ctail)) = x;
  183. }
  184.  
  185.  
  186. /* Emptiness predicate */
  187.  
  188. CQEmpty(queue_p)
  189. struct cqueue *queue_p;
  190. {
  191.     return (queue_p->chead == queue_p->ctail);
  192. }
  193.  
  194.  
  195. /* Fullness predicate */
  196.  
  197. CQFull(queue_p)
  198. struct cqueue *queue_p;
  199. {
  200.     return((queue_p->ctail+1 == queue_p->chead) ||
  201.         (queue_p->ctail == queue_p->cbottom &&
  202.          queue_p->chead == queue_p->ctop));
  203. }
  204.  
  205.  
  206. /* Peek at head of queue without disturbing it */
  207.  
  208. CQPeek(queue_p)
  209. struct cqueue *queue_p;
  210. {
  211.     return ( (queue_p->chead == queue_p->cbottom)  ?
  212.            *queue_p->ctop  :
  213.            queue_p->chead[1] );
  214. }
  215.  
  216.