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/libradius.h>
30 typedef struct fr_fifo_entry_t {
31 struct fr_fifo_entry_t *next;
36 fr_fifo_entry_t *head, **tail;
37 fr_fifo_entry_t *freelist;
41 fr_fifo_free_t freeNode;
45 fr_fifo_t *fr_fifo_create(int max_entries, fr_fifo_free_t freeNode)
49 if ((max_entries < 2) || (max_entries > (1024 * 1024))) return NULL;
51 fi = malloc(sizeof(*fi));
54 memset(fi, 0, sizeof(*fi));
56 fi->max_entries = max_entries;
57 fi->freeNode = freeNode;
62 static void fr_fifo_free_entries(fr_fifo_t *fi, fr_fifo_entry_t *head)
64 fr_fifo_entry_t *next;
69 if (fi->freeNode && head->data) fi->freeNode(head->data);
76 void fr_fifo_free(fr_fifo_t *fi)
80 fr_fifo_free_entries(fi, fi->head);
81 fr_fifo_free_entries(fi, fi->freelist);
86 static fr_fifo_entry_t *fr_fifo_alloc_entry(fr_fifo_t *fi)
88 fr_fifo_entry_t *entry;
92 fi->freelist = entry->next;
94 entry = malloc(sizeof(*entry));
95 if (!entry) return NULL;
98 memset(entry, 0, sizeof(*entry));
102 int fr_fifo_push(fr_fifo_t *fi, void *data)
104 fr_fifo_entry_t *entry;
106 if (!fi || !data) return 0;
108 if (fi->num_elements >= fi->max_entries) return 0;
110 entry = fr_fifo_alloc_entry(fi);
111 if (!entry) return 0;
119 fi->tail = &(entry->next);
126 static void fr_fifo_free_entry(fr_fifo_t *fi, fr_fifo_entry_t *entry)
129 entry->next = fi->freelist;
130 fi->freelist = entry;
134 void *fr_fifo_pop(fr_fifo_t *fi)
137 fr_fifo_entry_t *entry;
139 if (!fi || !fi->head) return NULL;
142 fi->head = entry->next;
145 fr_fifo_free_entry(fi, entry);
151 fi->num_elements = 0;
157 void *fr_fifo_peek(fr_fifo_t *fi)
159 if (!fi || !fi->head) return NULL;
161 return fi->head->data;
164 int fr_fifo_num_elements(fr_fifo_t *fi)
168 return fi->num_elements;
174 * cc -DTESTING -I .. fifo.c -o fifo
180 int main(int argc, char **argv)
185 fi = fr_fifo_create(MAX, NULL);
188 for (i = 0; i < MAX; i++) {
191 if (!fr_fifo_push(fi, &array[i])) exit(2);
194 for (i = 0; i < MAX; i++) {
199 fprintf(stderr, "No pop at %d\n", i);
203 if (*p != i) exit(4);