1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #pragma ident   "%Z%%M% %I%     %E% SMI"
  28 
  29 /*
  30  * Routines for manipulating a FIFO queue
  31  */
  32 
  33 #include <stdlib.h>
  34 
  35 #include "fifo.h"
  36 #include "memory.h"
  37 
  38 typedef struct fifonode {
  39         void *fn_data;
  40         struct fifonode *fn_next;
  41 } fifonode_t;
  42 
  43 struct fifo {
  44         fifonode_t *f_head;
  45         fifonode_t *f_tail;
  46 };
  47 
  48 fifo_t *
  49 fifo_new(void)
  50 {
  51         fifo_t *f;
  52 
  53         f = xcalloc(sizeof (fifo_t));
  54 
  55         return (f);
  56 }
  57 
  58 /* Add to the end of the fifo */
  59 void
  60 fifo_add(fifo_t *f, void *data)
  61 {
  62         fifonode_t *fn = xmalloc(sizeof (fifonode_t));
  63 
  64         fn->fn_data = data;
  65         fn->fn_next = NULL;
  66 
  67         if (f->f_tail == NULL)
  68                 f->f_head = f->f_tail = fn;
  69         else {
  70                 f->f_tail->fn_next = fn;
  71                 f->f_tail = fn;
  72         }
  73 }
  74 
  75 /* Remove from the front of the fifo */
  76 void *
  77 fifo_remove(fifo_t *f)
  78 {
  79         fifonode_t *fn;
  80         void *data;
  81 
  82         if ((fn = f->f_head) == NULL)
  83                 return (NULL);
  84 
  85         data = fn->fn_data;
  86         if ((f->f_head = fn->fn_next) == NULL)
  87                 f->f_tail = NULL;
  88 
  89         free(fn);
  90 
  91         return (data);
  92 }
  93 
  94 /*ARGSUSED*/
  95 static void
  96 fifo_nullfree(void *arg)
  97 {
  98         /* this function intentionally left blank */
  99 }
 100 
 101 /* Free an entire fifo */
 102 void
 103 fifo_free(fifo_t *f, void (*freefn)(void *))
 104 {
 105         fifonode_t *fn = f->f_head;
 106         fifonode_t *tmp;
 107 
 108         if (freefn == NULL)
 109                 freefn = fifo_nullfree;
 110 
 111         while (fn) {
 112                 (*freefn)(fn->fn_data);
 113 
 114                 tmp = fn;
 115                 fn = fn->fn_next;
 116                 free(tmp);
 117         }
 118 
 119         free(f);
 120 }
 121 
 122 int
 123 fifo_len(fifo_t *f)
 124 {
 125         fifonode_t *fn;
 126         int i;
 127 
 128         for (i = 0, fn = f->f_head; fn; fn = fn->fn_next, i++);
 129 
 130         return (i);
 131 }
 132 
 133 int
 134 fifo_empty(fifo_t *f)
 135 {
 136         return (f->f_head == NULL);
 137 }
 138 
 139 int
 140 fifo_iter(fifo_t *f, int (*iter)(void *data, void *arg), void *arg)
 141 {
 142         fifonode_t *fn;
 143         int rc;
 144         int ret = 0;
 145 
 146         for (fn = f->f_head; fn; fn = fn->fn_next) {
 147                 if ((rc = iter(fn->fn_data, arg)) < 0)
 148                         return (-1);
 149                 ret += rc;
 150         }
 151 
 152         return (ret);
 153 }