1 /*
2  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 #ifndef _KRB5_DB2_DBQUEUE_H
7 #define	_KRB5_DB2_DBQUEUE_H
8 
9 #pragma ident	"%Z%%M%	%I%	%E% SMI"
10 
11 #ifdef	__cplusplus
12 extern "C" {
13 #endif
14 
15 /*
16  * Copyright (c) 1991, 1993
17  *	The Regents of the University of California.  All rights reserved.
18  *
19  * Redistribution and use in source and binary forms, with or without
20  * modification, are permitted provided that the following conditions
21  * are met:
22  * 1. Redistributions of source code must retain the above copyright
23  *    notice, this list of conditions and the following disclaimer.
24  * 2. Redistributions in binary form must reproduce the above copyright
25  *    notice, this list of conditions and the following disclaimer in the
26  *    documentation and/or other materials provided with the distribution.
27  * 3. All advertising materials mentioning features or use of this software
28  *    must display the following acknowledgement:
29  *	This product includes software developed by the University of
30  *	California, Berkeley and its contributors.
31  * 4. Neither the name of the University nor the names of its contributors
32  *    may be used to endorse or promote products derived from this software
33  *    without specific prior written permission.
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
36  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
39  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45  * SUCH DAMAGE.
46  *
47  *	@(#)queue.h	8.3 (Berkeley) 12/13/93
48  */
49 
50 #ifndef	_QUEUE_H_
51 #define	_QUEUE_H_
52 
53 /*
54  * This file defines three types of data structures: lists, tail queues,
55  * and circular queues.
56  *
57  * A list is headed by a single forward pointer (or an array of forward
58  * pointers for a hash table header). The elements are doubly linked
59  * so that an arbitrary element can be removed without a need to
60  * traverse the list. New elements can be added to the list after
61  * an existing element or at the head of the list. A list may only be
62  * traversed in the forward direction.
63  *
64  * A tail queue is headed by a pair of pointers, one to the head of the
65  * list and the other to the tail of the list. The elements are doubly
66  * linked so that an arbitrary element can be removed without a need to
67  * traverse the list. New elements can be added to the list after
68  * an existing element, at the head of the list, or at the end of the
69  * list. A tail queue may only be traversed in the forward direction.
70  *
71  * A circle queue is headed by a pair of pointers, one to the head of the
72  * list and the other to the tail of the list. The elements are doubly
73  * linked so that an arbitrary element can be removed without a need to
74  * traverse the list. New elements can be added to the list before or after
75  * an existing element, at the head of the list, or at the end of the list.
76  * A circle queue may be traversed in either direction, but has a more
77  * complex end of list detection.
78  *
79  * For details on the use of these macros, see the queue(3) manual page.
80  */
81 
82 /*
83  * List definitions.
84  */
85 #define LIST_HEAD(name, type)						\
86 struct name {								\
87 	struct type *lh_first;	/* first element */			\
88 }
89 
90 #define LIST_ENTRY(type)						\
91 struct {								\
92 	struct type *le_next;	/* next element */			\
93 	struct type **le_prev;	/* address of previous next element */	\
94 }
95 
96 /*
97  * List functions.
98  */
99 #define	LIST_INIT(head) {						\
100 	(head)->lh_first = NULL;					\
101 }
102 
103 #define LIST_INSERT_AFTER(listelm, elm, field) {			\
104 	if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)	\
105 		(listelm)->field.le_next->field.le_prev =		\
106 		    &(elm)->field.le_next;				\
107 	(listelm)->field.le_next = (elm);				\
108 	(elm)->field.le_prev = &(listelm)->field.le_next;		\
109 }
110 
111 #define LIST_INSERT_HEAD(head, elm, field) {				\
112 	if (((elm)->field.le_next = (head)->lh_first) != NULL)		\
113 		(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
114 	(head)->lh_first = (elm);					\
115 	(elm)->field.le_prev = &(head)->lh_first;			\
116 }
117 
118 #define LIST_REMOVE(elm, field) {					\
119 	if ((elm)->field.le_next != NULL)				\
120 		(elm)->field.le_next->field.le_prev = 			\
121 		    (elm)->field.le_prev;				\
122 	*(elm)->field.le_prev = (elm)->field.le_next;			\
123 }
124 
125 /*
126  * Tail queue definitions.
127  */
128 #define TAILQ_HEAD(name, type)						\
129 struct name {								\
130 	struct type *tqh_first;	/* first element */			\
131 	struct type **tqh_last;	/* addr of last next element */		\
132 }
133 
134 #define TAILQ_ENTRY(type)						\
135 struct {								\
136 	struct type *tqe_next;	/* next element */			\
137 	struct type **tqe_prev;	/* address of previous next element */	\
138 }
139 
140 /*
141  * Tail queue functions.
142  */
143 #define	TAILQ_INIT(head) {						\
144 	(head)->tqh_first = NULL;					\
145 	(head)->tqh_last = &(head)->tqh_first;				\
146 }
147 
148 #define TAILQ_INSERT_HEAD(head, elm, field) {				\
149 	if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)	\
150 		(elm)->field.tqe_next->field.tqe_prev =			\
151 		    &(elm)->field.tqe_next;				\
152 	else								\
153 		(head)->tqh_last = &(elm)->field.tqe_next;		\
154 	(head)->tqh_first = (elm);					\
155 	(elm)->field.tqe_prev = &(head)->tqh_first;			\
156 }
157 
158 #define TAILQ_INSERT_TAIL(head, elm, field) {				\
159 	(elm)->field.tqe_next = NULL;					\
160 	(elm)->field.tqe_prev = (head)->tqh_last;			\
161 	*(head)->tqh_last = (elm);					\
162 	(head)->tqh_last = &(elm)->field.tqe_next;			\
163 }
164 
165 #define TAILQ_INSERT_AFTER(head, listelm, elm, field) {			\
166 	if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
167 		(elm)->field.tqe_next->field.tqe_prev = 		\
168 		    &(elm)->field.tqe_next;				\
169 	else								\
170 		(head)->tqh_last = &(elm)->field.tqe_next;		\
171 	(listelm)->field.tqe_next = (elm);				\
172 	(elm)->field.tqe_prev = &(listelm)->field.tqe_next;		\
173 }
174 
175 #define TAILQ_REMOVE(head, elm, field) {				\
176 	if (((elm)->field.tqe_next) != NULL)				\
177 		(elm)->field.tqe_next->field.tqe_prev = 		\
178 		    (elm)->field.tqe_prev;				\
179 	else								\
180 		(head)->tqh_last = (elm)->field.tqe_prev;		\
181 	*(elm)->field.tqe_prev = (elm)->field.tqe_next;			\
182 }
183 
184 /*
185  * Circular queue definitions.
186  */
187 #define CIRCLEQ_HEAD(name, type)					\
188 struct name {								\
189 	struct type *cqh_first;		/* first element */		\
190 	struct type *cqh_last;		/* last element */		\
191 }
192 
193 #define CIRCLEQ_ENTRY(type)						\
194 struct {								\
195 	struct type *cqe_next;		/* next element */		\
196 	struct type *cqe_prev;		/* previous element */		\
197 }
198 
199 /*
200  * Circular queue functions.
201  */
202 #define	CIRCLEQ_INIT(head) {						\
203 	(head)->cqh_first = (void *)(head);				\
204 	(head)->cqh_last = (void *)(head);				\
205 }
206 
207 #define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) {		\
208 	(elm)->field.cqe_next = (listelm)->field.cqe_next;		\
209 	(elm)->field.cqe_prev = (listelm);				\
210 	if ((listelm)->field.cqe_next == (void *)(head))		\
211 		(head)->cqh_last = (elm);				\
212 	else								\
213 		(listelm)->field.cqe_next->field.cqe_prev = (elm);	\
214 	(listelm)->field.cqe_next = (elm);				\
215 }
216 
217 #define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) {		\
218 	(elm)->field.cqe_next = (listelm);				\
219 	(elm)->field.cqe_prev = (listelm)->field.cqe_prev;		\
220 	if ((listelm)->field.cqe_prev == (void *)(head))		\
221 		(head)->cqh_first = (elm);				\
222 	else								\
223 		(listelm)->field.cqe_prev->field.cqe_next = (elm);	\
224 	(listelm)->field.cqe_prev = (elm);				\
225 }
226 
227 #define CIRCLEQ_INSERT_HEAD(head, elm, field) {				\
228 	(elm)->field.cqe_next = (head)->cqh_first;			\
229 	(elm)->field.cqe_prev = (void *)(head);				\
230 	if ((head)->cqh_last == (void *)(head))				\
231 		(head)->cqh_last = (elm);				\
232 	else								\
233 		(head)->cqh_first->field.cqe_prev = (elm);		\
234 	(head)->cqh_first = (elm);					\
235 }
236 
237 #define CIRCLEQ_INSERT_TAIL(head, elm, field) {				\
238 	(elm)->field.cqe_next = (void *)(head);				\
239 	(elm)->field.cqe_prev = (head)->cqh_last;			\
240 	if ((head)->cqh_first == (void *)(head))			\
241 		(head)->cqh_first = (elm);				\
242 	else								\
243 		(head)->cqh_last->field.cqe_next = (elm);		\
244 	(head)->cqh_last = (elm);					\
245 }
246 
247 #define	CIRCLEQ_REMOVE(head, elm, field) {				\
248 	if ((elm)->field.cqe_next == (void *)(head))			\
249 		(head)->cqh_last = (elm)->field.cqe_prev;		\
250 	else								\
251 		(elm)->field.cqe_next->field.cqe_prev =			\
252 		    (elm)->field.cqe_prev;				\
253 	if ((elm)->field.cqe_prev == (void *)(head))			\
254 		(head)->cqh_first = (elm)->field.cqe_next;		\
255 	else								\
256 		(elm)->field.cqe_prev->field.cqe_next =			\
257 		    (elm)->field.cqe_next;				\
258 }
259 #endif	/* !_QUEUE_H_ */
260 
261 #ifdef	__cplusplus
262 }
263 #endif
264 
265 #endif	/* !_KRB5_DB2_DBQUEUE_H */
266