4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * @(#)queue.h 8.5 (Berkeley) 8/20/94
42 * This file defines three types of data structures: lists, tail queues,
43 * and circular queues.
45 * A list is headed by a single forward pointer (or an array of forward
46 * pointers for a hash table header). The elements are doubly linked
47 * so that an arbitrary element can be removed without a need to
48 * traverse the list. New elements can be added to the list before
49 * or after an existing element or at the head of the list. A list
50 * may only be traversed in the forward direction.
52 * A tail queue is headed by a pair of pointers, one to the head of the
53 * list and the other to the tail of the list. The elements are doubly
54 * linked so that an arbitrary element can be removed without a need to
55 * traverse the list. New elements can be added to the list before or
56 * after an existing element, at the head of the list, or at the end of
57 * the list. A tail queue may only be traversed in the forward direction.
59 * A circle queue is headed by a pair of pointers, one to the head of the
60 * list and the other to the tail of the list. The elements are doubly
61 * linked so that an arbitrary element can be removed without a need to
62 * traverse the list. New elements can be added to the list before or after
63 * an existing element, at the head of the list, or at the end of the list.
64 * A circle queue may be traversed in either direction, but has a more
65 * complex end of list detection.
67 * For details on the use of these macros, see the queue(3) manual page.
73 #define LIST_HEAD(name, type) \
75 struct type *lh_first; /* first element */ \
78 #define LIST_ENTRY(type) \
80 struct type *le_next; /* next element */ \
81 struct type **le_prev; /* address of previous next element */ \
87 #define LIST_INIT(head) { \
88 (head)->lh_first = NULL; \
91 #define LIST_INSERT_AFTER(listelm, elm, field) { \
92 if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
93 (listelm)->field.le_next->field.le_prev = \
94 &(elm)->field.le_next; \
95 (listelm)->field.le_next = (elm); \
96 (elm)->field.le_prev = &(listelm)->field.le_next; \
99 #define LIST_INSERT_BEFORE(listelm, elm, field) { \
100 (elm)->field.le_prev = (listelm)->field.le_prev; \
101 (elm)->field.le_next = (listelm); \
102 *(listelm)->field.le_prev = (elm); \
103 (listelm)->field.le_prev = &(elm)->field.le_next; \
106 #define LIST_INSERT_HEAD(head, elm, field) { \
107 if (((elm)->field.le_next = (head)->lh_first) != NULL) \
108 (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
109 (head)->lh_first = (elm); \
110 (elm)->field.le_prev = &(head)->lh_first; \
113 #define LIST_REMOVE(elm, field) { \
114 if ((elm)->field.le_next != NULL) \
115 (elm)->field.le_next->field.le_prev = \
116 (elm)->field.le_prev; \
117 *(elm)->field.le_prev = (elm)->field.le_next; \
121 * Tail queue definitions.
123 #define TAILQ_HEAD(name, type) \
125 struct type *tqh_first; /* first element */ \
126 struct type **tqh_last; /* addr of last next element */ \
129 #define TAILQ_ENTRY(type) \
131 struct type *tqe_next; /* next element */ \
132 struct type **tqe_prev; /* address of previous next element */ \
136 * Tail queue functions.
138 #define TAILQ_INIT(head) { \
139 (head)->tqh_first = NULL; \
140 (head)->tqh_last = &(head)->tqh_first; \
143 #define TAILQ_INSERT_HEAD(head, elm, field) { \
144 if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
145 (head)->tqh_first->field.tqe_prev = \
146 &(elm)->field.tqe_next; \
148 (head)->tqh_last = &(elm)->field.tqe_next; \
149 (head)->tqh_first = (elm); \
150 (elm)->field.tqe_prev = &(head)->tqh_first; \
153 #define TAILQ_INSERT_TAIL(head, elm, field) { \
154 (elm)->field.tqe_next = NULL; \
155 (elm)->field.tqe_prev = (head)->tqh_last; \
156 *(head)->tqh_last = (elm); \
157 (head)->tqh_last = &(elm)->field.tqe_next; \
160 #define TAILQ_INSERT_AFTER(head, listelm, elm, field) { \
161 if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
162 (elm)->field.tqe_next->field.tqe_prev = \
163 &(elm)->field.tqe_next; \
165 (head)->tqh_last = &(elm)->field.tqe_next; \
166 (listelm)->field.tqe_next = (elm); \
167 (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
170 #define TAILQ_INSERT_BEFORE(listelm, elm, field) { \
171 (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
172 (elm)->field.tqe_next = (listelm); \
173 *(listelm)->field.tqe_prev = (elm); \
174 (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
177 #define TAILQ_REMOVE(head, elm, field) { \
178 if (((elm)->field.tqe_next) != NULL) \
179 (elm)->field.tqe_next->field.tqe_prev = \
180 (elm)->field.tqe_prev; \
182 (head)->tqh_last = (elm)->field.tqe_prev; \
183 *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
187 * Circular queue definitions.
189 #define CIRCLEQ_HEAD(name, type) \
191 struct type *cqh_first; /* first element */ \
192 struct type *cqh_last; /* last element */ \
195 #define CIRCLEQ_ENTRY(type) \
197 struct type *cqe_next; /* next element */ \
198 struct type *cqe_prev; /* previous element */ \
202 * Circular queue functions.
204 #define CIRCLEQ_INIT(head) { \
205 (head)->cqh_first = (void *)(head); \
206 (head)->cqh_last = (void *)(head); \
209 #define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) { \
210 (elm)->field.cqe_next = (listelm)->field.cqe_next; \
211 (elm)->field.cqe_prev = (listelm); \
212 if ((listelm)->field.cqe_next == (void *)(head)) \
213 (head)->cqh_last = (elm); \
215 (listelm)->field.cqe_next->field.cqe_prev = (elm); \
216 (listelm)->field.cqe_next = (elm); \
219 #define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) { \
220 (elm)->field.cqe_next = (listelm); \
221 (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
222 if ((listelm)->field.cqe_prev == (void *)(head)) \
223 (head)->cqh_first = (elm); \
225 (listelm)->field.cqe_prev->field.cqe_next = (elm); \
226 (listelm)->field.cqe_prev = (elm); \
229 #define CIRCLEQ_INSERT_HEAD(head, elm, field) { \
230 (elm)->field.cqe_next = (head)->cqh_first; \
231 (elm)->field.cqe_prev = (void *)(head); \
232 if ((head)->cqh_last == (void *)(head)) \
233 (head)->cqh_last = (elm); \
235 (head)->cqh_first->field.cqe_prev = (elm); \
236 (head)->cqh_first = (elm); \
239 #define CIRCLEQ_INSERT_TAIL(head, elm, field) { \
240 (elm)->field.cqe_next = (void *)(head); \
241 (elm)->field.cqe_prev = (head)->cqh_last; \
242 if ((head)->cqh_first == (void *)(head)) \
243 (head)->cqh_first = (elm); \
245 (head)->cqh_last->field.cqe_next = (elm); \
246 (head)->cqh_last = (elm); \
249 #define CIRCLEQ_REMOVE(head, elm, field) { \
250 if ((elm)->field.cqe_next == (void *)(head)) \
251 (head)->cqh_last = (elm)->field.cqe_prev; \
253 (elm)->field.cqe_next->field.cqe_prev = \
254 (elm)->field.cqe_prev; \
255 if ((elm)->field.cqe_prev == (void *)(head)) \
256 (head)->cqh_first = (elm)->field.cqe_next; \
258 (elm)->field.cqe_prev->field.cqe_next = \
259 (elm)->field.cqe_next; \
261 #endif /* !_SYS_QUEUE_H_ */