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