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,2006 The FreeRADIUS server project
22 * Copyright 2005 Alan DeKok <aland@ox.org>
25 #include <freeradius-devel/ident.h>
28 #include <freeradius-devel/autoconf.h>
33 #include <freeradius-devel/missing.h>
34 #include <freeradius-devel/libradius.h>
36 typedef struct lrad_fifo_entry_t {
37 struct lrad_fifo_entry_t *next;
42 lrad_fifo_entry_t *head, **tail;
43 lrad_fifo_entry_t *freelist;
47 lrad_fifo_free_t freeNode;
51 lrad_fifo_t *lrad_fifo_create(int max_entries, lrad_fifo_free_t freeNode)
55 if ((max_entries < 2) || (max_entries > (1024 * 1024))) return NULL;
57 fi = malloc(sizeof(*fi));
60 memset(fi, 0, sizeof(*fi));
62 fi->max_entries = max_entries;
63 fi->freeNode = freeNode;
68 static void lrad_fifo_free_entries(lrad_fifo_t *fi, lrad_fifo_entry_t *head)
70 lrad_fifo_entry_t *next;
75 if (fi->freeNode && head->data) fi->freeNode(head->data);
82 void lrad_fifo_free(lrad_fifo_t *fi)
86 lrad_fifo_free_entries(fi, fi->head);
87 lrad_fifo_free_entries(fi, fi->freelist);
92 static lrad_fifo_entry_t *lrad_fifo_alloc_entry(lrad_fifo_t *fi)
94 lrad_fifo_entry_t *entry;
98 fi->freelist = entry->next;
100 entry = malloc(sizeof(*entry));
101 if (!entry) return NULL;
104 memset(entry, 0, sizeof(*entry));
108 int lrad_fifo_push(lrad_fifo_t *fi, void *data)
110 lrad_fifo_entry_t *entry;
112 if (!fi || !data) return 0;
114 if (fi->num_elements >= fi->max_entries) return 0;
116 entry = lrad_fifo_alloc_entry(fi);
117 if (!entry) return 0;
125 fi->tail = &(entry->next);
132 static void lrad_fifo_free_entry(lrad_fifo_t *fi, lrad_fifo_entry_t *entry)
135 entry->next = fi->freelist;
136 fi->freelist = entry->next;
140 void *lrad_fifo_pop(lrad_fifo_t *fi)
143 lrad_fifo_entry_t *entry;
145 if (!fi || !fi->head) return 0;
148 fi->head = entry->next;
151 lrad_fifo_free_entry(fi, entry);
157 fi->num_elements = 0;
166 * cc -DTESTING -I .. fifo.c -o fifo
172 int main(int argc, char **argv)
177 fi = lrad_fifo_create(MAX, NULL);
180 for (i = 0; i < MAX; i++) {
183 if (!lrad_fifo_push(fi, &array[i])) exit(2);
186 for (i = 0; i < MAX; i++) {
189 p = lrad_fifo_pop(fi);
191 fprintf(stderr, "No pop at %d\n", i);
195 if (*p != i) exit(4);