2 * fifo.c Non-thread-safe fifo (FIFO) implementation, based
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * Copyright 2005 The FreeRADIUS server project
22 * Copyright 2005 Alan DeKok <aland@ox.org>
25 static const char rcsid[] = "$Id$";
27 #include <freeradius-devel/autoconf.h>
32 #include <freeradius-devel/missing.h>
33 #include <freeradius-devel/libradius.h>
35 typedef struct lrad_fifo_entry_t {
36 struct lrad_fifo_entry_t *next;
41 lrad_fifo_entry_t *head, **tail;
42 lrad_fifo_entry_t *freelist;
46 lrad_fifo_free_t freeNode;
50 lrad_fifo_t *lrad_fifo_create(int max_entries, lrad_fifo_free_t freeNode)
54 if ((max_entries < 2) || (max_entries > (1024 * 1024))) return NULL;
56 fi = malloc(sizeof(*fi));
59 memset(fi, 0, sizeof(*fi));
61 fi->max_entries = max_entries;
62 fi->freeNode = freeNode;
67 static void lrad_fifo_free_entries(lrad_fifo_t *fi, lrad_fifo_entry_t *head)
69 lrad_fifo_entry_t *next;
74 if (fi->freeNode && head->data) fi->freeNode(head->data);
81 void lrad_fifo_free(lrad_fifo_t *fi)
85 lrad_fifo_free_entries(fi, fi->head);
86 lrad_fifo_free_entries(fi, fi->freelist);
91 static lrad_fifo_entry_t *lrad_fifo_alloc_entry(lrad_fifo_t *fi)
93 lrad_fifo_entry_t *entry;
97 fi->freelist = entry->next;
99 entry = malloc(sizeof(*entry));
100 if (!entry) return NULL;
103 memset(entry, 0, sizeof(*entry));
107 int lrad_fifo_push(lrad_fifo_t *fi, void *data)
109 lrad_fifo_entry_t *entry;
111 if (!fi || !data) return 0;
113 if (fi->num_elements >= fi->max_entries) return 0;
115 entry = lrad_fifo_alloc_entry(fi);
116 if (!entry) return 0;
124 fi->tail = &(entry->next);
131 static void lrad_fifo_free_entry(lrad_fifo_t *fi, lrad_fifo_entry_t *entry)
134 entry->next = fi->freelist;
135 fi->freelist = entry->next;
139 void *lrad_fifo_pop(lrad_fifo_t *fi)
142 lrad_fifo_entry_t *entry;
144 if (!fi || !fi->head) return 0;
147 fi->head = entry->next;
150 lrad_fifo_free_entry(fi, entry);
156 fi->num_elements = 0;
165 * cc -DTESTING -I .. fifo.c -o fifo
171 int main(int argc, char **argv)
176 fi = lrad_fifo_create(MAX, NULL);
179 for (i = 0; i < MAX; i++) {
182 if (!lrad_fifo_push(fi, &array[i])) exit(2);
185 for (i = 0; i < MAX; i++) {
188 p = lrad_fifo_pop(fi);
190 fprintf(stderr, "No pop at %d\n", i);
194 if (*p != i) exit(4);