1 /* $OpenBSD: queue.h,v 1.45 2018/07/12 14:22:54 sashan Exp $ */ 2 /* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ 3 4 /* 5 * Copyright (c) 1991, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * @(#)queue.h 8.5 (Berkeley) 8/20/94 33 */ 34 module libressl_d.compat.sys.queue; 35 36 37 //#include <sys/_null.h> 38 39 extern (C): 40 nothrow @nogc: 41 42 /* 43 * This file defines five types of data structures: singly-linked lists, 44 * lists, simple queues, tail queues and XOR simple queues. 45 * 46 * 47 * A singly-linked list is headed by a single forward pointer. The elements 48 * are singly linked for minimum space and pointer manipulation overhead at 49 * the expense of O(n) removal for arbitrary elements. New elements can be 50 * added to the list after an existing element or at the head of the list. 51 * Elements being removed from the head of the list should use the explicit 52 * macro for this purpose for optimum efficiency. A singly-linked list may 53 * only be traversed in the forward direction. Singly-linked lists are ideal 54 * for applications with large datasets and few or no removals or for 55 * implementing a LIFO queue. 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 before 61 * or after an existing element or at the head of the list. A list 62 * may only be traversed in the forward direction. 63 * 64 * A simple 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 singly 66 * linked to save space, so elements can only be removed from the 67 * head of the list. New elements can be added to the list before or after 68 * an existing element, at the head of the list, or at the end of the 69 * list. A simple queue may only be traversed in the forward direction. 70 * 71 * A tail 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 75 * after an existing element, at the head of the list, or at the end of 76 * the list. A tail queue may be traversed in either direction. 77 * 78 * An XOR simple queue is used in the same way as a regular simple queue. 79 * The difference is that the head structure also includes a "cookie" that 80 * is XOR'd with the queue pointer (first, last or next) to generate the 81 * real pointer value. 82 * 83 * For details on the use of these macros, see the queue(3) manual page. 84 */ 85 86 //#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC)) 87 version (none) { 88 enum _Q_INVALID = cast(void*)(-1); 89 90 pragma(inline, true) 91 pure nothrow @trusted @nogc @live 92 void _Q_INVALIDATE(scope void* a) 93 94 in 95 { 96 assert(a != null); 97 } 98 99 do 100 { 101 a = ._Q_INVALID; 102 } 103 } else { 104 pragma(inline, true) 105 pure nothrow @trusted @nogc @live 106 void _Q_INVALIDATE(scope void* a) 107 108 do 109 { 110 } 111 } 112 113 /* 114 * Singly-linked List definitions. 115 */ 116 template SLIST_HEAD(string name, string type) 117 { 118 enum SLIST_HEAD = "struct " ~ name ~ " { " ~ type ~ "* slh_first; /* first element */ }"; 119 } 120 121 pragma(inline, true) 122 pure nothrow @safe @nogc @live 123 HEAD SLIST_HEAD_INITIALIZER(HEAD)(scope const HEAD* head) 124 if (is(HEAD == struct)) 125 126 do 127 { 128 return HEAD.init; 129 } 130 131 template SLIST_ENTRY(string type) 132 { 133 enum SLIST_ENTRY = "struct { " ~ type ~ "* sle_next; /* next element */ }"; 134 } 135 136 /* 137 * Singly-linked List access methods. 138 */ 139 //#define SLIST_FIRST(head) ((head)->slh_first) 140 //#define SLIST_END(head) NULL 141 //#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) 142 //#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) 143 144 //#define SLIST_FOREACH(var, head, field) for ((var) = SLIST_FIRST(head); (var) != SLIST_END(head); (var) = SLIST_NEXT(var, field)) 145 146 //#define SLIST_FOREACH_SAFE(var, head, field, tvar) for ((var) = SLIST_FIRST(head); (var) && ((tvar) = SLIST_NEXT(var, field), 1); (var) = (tvar)) 147 148 /* 149 * Singly-linked List functions. 150 */ 151 //#define SLIST_INIT(head) { SLIST_FIRST(head) = SLIST_END(head); } 152 153 //#define SLIST_INSERT_AFTER(slistelm, elm, field) do { (elm)->field.sle_next = (slistelm)->field.sle_next; (slistelm)->field.sle_next = (elm); } while (0) 154 155 //#define SLIST_INSERT_HEAD(head, elm, field) do { (elm)->field.sle_next = (head)->slh_first; (head)->slh_first = (elm); } while (0) 156 157 //#define SLIST_REMOVE_AFTER(elm, field) do { (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; } while (0) 158 159 //#define SLIST_REMOVE_HEAD(head, field) do { (head)->slh_first = (head)->slh_first->field.sle_next; } while (0) 160 161 //#define SLIST_REMOVE(head, elm, type, field) do { if ((head)->slh_first == (elm)) { SLIST_REMOVE_HEAD((head), field); } else { struct type* curelm = (head)->slh_first; while (curelm->field.sle_next != (elm)) curelm = curelm->field.sle_next; curelm->field.sle_next = curelm->field.sle_next->field.sle_next; } _Q_INVALIDATE((elm)->field.sle_next); } while (0) 162 163 /* 164 * List definitions. 165 */ 166 template LIST_HEAD(string name, string type) 167 { 168 enum LIST_HEAD = "struct " ~ name ~ " { " ~ type ~ "* lh_first; /* first element */ }"; 169 } 170 171 pragma(inline, true) 172 pure nothrow @safe @nogc @live 173 HEAD LIST_HEAD_INITIALIZER(HEAD)(scope const HEAD* head) 174 if (is(HEAD == struct)) 175 176 do 177 { 178 return HEAD.init; 179 } 180 181 template LIST_ENTRY(string type) 182 { 183 enum LIST_ENTRY = "struct { " ~ type ~ "* le_next; /* next element */ " ~ type ~ "** le_prev; /* address of previous next element */ }"; 184 } 185 186 /* 187 * List access methods. 188 */ 189 //#define LIST_FIRST(head) ((head)->lh_first) 190 //#define LIST_END(head) NULL 191 //#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) 192 //#define LIST_NEXT(elm, field) ((elm)->field.le_next) 193 194 //#define LIST_FOREACH(var, head, field) for ((var) = LIST_FIRST(head); (var) != LIST_END(head); (var) = LIST_NEXT(var, field)) 195 196 //#define LIST_FOREACH_SAFE(var, head, field, tvar) for ((var) = LIST_FIRST(head); (var) && ((tvar) = LIST_NEXT(var, field), 1); (var) = (tvar)) 197 198 /* 199 * List functions. 200 */ 201 //#define LIST_INIT(head) do { LIST_FIRST(head) = LIST_END(head); } while (0) 202 203 //#define LIST_INSERT_AFTER(listelm, elm, field) do { if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) (listelm)->field.le_next->field.le_prev = &(elm)->field.le_next; (listelm)->field.le_next = (elm); (elm)->field.le_prev = &(listelm)->field.le_next; } while (0) 204 205 //#define LIST_INSERT_BEFORE(listelm, elm, field) do { (elm)->field.le_prev = (listelm)->field.le_prev; (elm)->field.le_next = (listelm); *(listelm)->field.le_prev = (elm); (listelm)->field.le_prev = &(elm)->field.le_next; } while (0) 206 207 //#define LIST_INSERT_HEAD(head, elm, field) do { if (((elm)->field.le_next = (head)->lh_first) != NULL) (head)->lh_first->field.le_prev = &(elm)->field.le_next; (head)->lh_first = (elm); (elm)->field.le_prev = &(head)->lh_first; } while (0) 208 209 //#define LIST_REMOVE(elm, field) do { if ((elm)->field.le_next != NULL) (elm)->field.le_next->field.le_prev = (elm)->field.le_prev; *(elm)->field.le_prev = (elm)->field.le_next; _Q_INVALIDATE((elm)->field.le_prev); _Q_INVALIDATE((elm)->field.le_next); } while (0) 210 211 //#define LIST_REPLACE(elm, elm2, field) do { if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) (elm2)->field.le_next->field.le_prev = &(elm2)->field.le_next; (elm2)->field.le_prev = (elm)->field.le_prev; *(elm2)->field.le_prev = (elm2); _Q_INVALIDATE((elm)->field.le_prev); _Q_INVALIDATE((elm)->field.le_next); } while (0) 212 213 /* 214 * Simple queue definitions. 215 */ 216 template SIMPLEQ_HEAD(string name, string type) 217 { 218 enum SIMPLEQ_HEAD = "struct " ~ name ~ " { " ~ type ~ "* sqh_first; /* first element */ " ~ type ~ "** sqh_last; /* addr of last next element */ }"; 219 } 220 221 pragma(inline, true) 222 pure nothrow @trusted @nogc @live 223 HEAD LIST_HEAD_INITIALIZER(HEAD)(HEAD* head) 224 if (is(HEAD == struct)) 225 226 in 227 { 228 assert(head != null); 229 } 230 231 do 232 { 233 HEAD output = 234 { 235 null, 236 &(head).sqh_first, 237 }; 238 239 return output; 240 } 241 242 template SIMPLEQ_ENTRY(string type) 243 { 244 enum SIMPLEQ_ENTRY = "struct { " ~ type ~ "* sqe_next; /* next element */ }"; 245 } 246 247 /* 248 * Simple queue access methods. 249 */ 250 //#define SIMPLEQ_FIRST(head) ((head)->sqh_first) 251 //#define SIMPLEQ_END(head) NULL 252 //#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) 253 //#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) 254 255 //#define SIMPLEQ_FOREACH(var, head, field) for ((var) = SIMPLEQ_FIRST(head); (var) != SIMPLEQ_END(head); (var) = SIMPLEQ_NEXT(var, field)) 256 257 //#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) for ((var) = SIMPLEQ_FIRST(head); (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); (var) = (tvar)) 258 259 /* 260 * Simple queue functions. 261 */ 262 //#define SIMPLEQ_INIT(head) do { (head)->sqh_first = NULL; (head)->sqh_last = &(head)->sqh_first; } while (0) 263 264 //#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) (head)->sqh_last = &(elm)->field.sqe_next; (head)->sqh_first = (elm); } while (0) 265 266 //#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { (elm)->field.sqe_next = NULL; *(head)->sqh_last = (elm); (head)->sqh_last = &(elm)->field.sqe_next; } while (0) 267 268 //#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL) (head)->sqh_last = &(elm)->field.sqe_next; (listelm)->field.sqe_next = (elm); } while (0) 269 270 //#define SIMPLEQ_REMOVE_HEAD(head, field) do { if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) (head)->sqh_last = &(head)->sqh_first; } while (0) 271 272 //#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) == NULL) (head)->sqh_last = &(elm)->field.sqe_next; } while (0) 273 274 //#define SIMPLEQ_CONCAT(head1, head2) do { if (!SIMPLEQ_EMPTY((head2))) { *(head1)->sqh_last = (head2)->sqh_first; (head1)->sqh_last = (head2)->sqh_last; SIMPLEQ_INIT((head2)); } } while (0) 275 276 /* 277 * XOR Simple queue definitions. 278 */ 279 template XSIMPLEQ_HEAD(string name, string type) 280 { 281 enum XSIMPLEQ_HEAD = "struct " ~ name ~ " { " ~ type ~ "* sqx_first; /* first element */ " ~ type ~ "** sqx_last; /* addr of last next element */ core.stdc.config.c_ulong sqx_cookie; }"; 282 } 283 284 template XSIMPLEQ_ENTRY(string type) 285 { 286 enum XSIMPLEQ_ENTRY = "struct { " ~ type ~ "* sqx_next; /* next element */ }"; 287 } 288 289 /* 290 * XOR Simple queue access methods. 291 */ 292 //#define XSIMPLEQ_XOR(head, ptr) ((__typeof(ptr))((head)->sqx_cookie ^ (unsigned long) (ptr))) 293 //#define XSIMPLEQ_FIRST(head) XSIMPLEQ_XOR(head, ((head)->sqx_first)) 294 //#define XSIMPLEQ_END(head) NULL 295 //#define XSIMPLEQ_EMPTY(head) (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head)) 296 //#define XSIMPLEQ_NEXT(head, elm, field) XSIMPLEQ_XOR(head, ((elm)->field.sqx_next)) 297 298 //#define XSIMPLEQ_FOREACH(var, head, field) for ((var) = XSIMPLEQ_FIRST(head); (var) != XSIMPLEQ_END(head); (var) = XSIMPLEQ_NEXT(head, var, field)) 299 300 //#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar) for ((var) = XSIMPLEQ_FIRST(head); (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); (var) = (tvar)) 301 302 /* 303 * XOR Simple queue functions. 304 */ 305 //#define XSIMPLEQ_INIT(head) do { arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); (head)->sqx_first = XSIMPLEQ_XOR(head, NULL); (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); } while (0) 306 307 //#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do { if (((elm)->field.sqx_next = (head)->sqx_first) == XSIMPLEQ_XOR(head, NULL)) (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); (head)->sqx_first = XSIMPLEQ_XOR(head, (elm)); } while (0) 308 309 //#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do { (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL); *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); } while (0) 310 311 //#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { if (((elm)->field.sqx_next = (listelm)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)); } while (0) 312 313 //#define XSIMPLEQ_REMOVE_HEAD(head, field) do { if (((head)->sqx_first = XSIMPLEQ_XOR(head, (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); } while (0) 314 315 //#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do { if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)->field.sqx_next)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); } while (0) 316 317 /* 318 * Tail queue definitions. 319 */ 320 template TAILQ_HEAD(string name, string type) 321 { 322 enum TAILQ_HEAD = "struct " ~ name ~ " { " ~ type ~ "* tqh_first; /* first element */ " ~ type ~ "** tqh_last; /* addr of last next element */ }"; 323 } 324 325 pragma(inline, true) 326 pure nothrow @trusted @nogc @live 327 HEAD TAILQ_HEAD_INITIALIZER(HEAD)(HEAD* head) 328 if (is(HEAD == struct)) 329 330 in 331 { 332 assert(head != null); 333 } 334 335 do 336 { 337 HEAD output = 338 { 339 null, 340 &(head).tqh_first, 341 }; 342 343 return output; 344 } 345 346 template TAILQ_ENTRY(string type) 347 { 348 enum TAILQ_ENTRY = "struct { " ~ type ~ "* tqe_next; /* next element */ " ~ type ~ "** tqe_prev; /* address of previous next element */ }"; 349 } 350 351 /* 352 * Tail queue access methods. 353 */ 354 //#define TAILQ_FIRST(head) ((head)->tqh_first) 355 //#define TAILQ_END(head) NULL 356 //#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) 357 //#define TAILQ_LAST(head, headname) (*(((struct headname*) ((head)->tqh_last))->tqh_last)) 358 /* XXX */ 359 //#define TAILQ_PREV(elm, headname, field) (*(((struct headname*) ((elm)->field.tqe_prev))->tqh_last)) 360 //#define TAILQ_EMPTY(head) (TAILQ_FIRST(head) == TAILQ_END(head)) 361 362 //#define TAILQ_FOREACH(var, head, field) for ((var) = TAILQ_FIRST(head); (var) != TAILQ_END(head); (var) = TAILQ_NEXT(var, field)) 363 364 //#define TAILQ_FOREACH_SAFE(var, head, field, tvar) for ((var) = TAILQ_FIRST(head); (var) != TAILQ_END(head) && ((tvar) = TAILQ_NEXT(var, field), 1); (var) = (tvar)) 365 366 //#define TAILQ_FOREACH_REVERSE(var, head, headname, field) for ((var) = TAILQ_LAST(head, headname); (var) != TAILQ_END(head); (var) = TAILQ_PREV(var, headname, field)) 367 368 //#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) for ((var) = TAILQ_LAST(head, headname); (var) != TAILQ_END(head) && ((tvar) = TAILQ_PREV(var, headname, field), 1); (var) = (tvar)) 369 370 /* 371 * Tail queue functions. 372 */ 373 //#define TAILQ_INIT(head) do { (head)->tqh_first = NULL; (head)->tqh_last = &(head)->tqh_first; } while (0) 374 375 //#define TAILQ_INSERT_HEAD(head, elm, field) do { if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) (head)->tqh_first->field.tqe_prev = &(elm)->field.tqe_next; else (head)->tqh_last = &(elm)->field.tqe_next; (head)->tqh_first = (elm); (elm)->field.tqe_prev = &(head)->tqh_first; } while (0) 376 377 //#define TAILQ_INSERT_TAIL(head, elm, field) do { (elm)->field.tqe_next = NULL; (elm)->field.tqe_prev = (head)->tqh_last; *(head)->tqh_last = (elm); (head)->tqh_last = &(elm)->field.tqe_next; } while (0) 378 379 //#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL) (elm)->field.tqe_next->field.tqe_prev = &(elm)->field.tqe_next; else (head)->tqh_last = &(elm)->field.tqe_next; (listelm)->field.tqe_next = (elm); (elm)->field.tqe_prev = &(listelm)->field.tqe_next; } while (0) 380 381 //#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { (elm)->field.tqe_prev = (listelm)->field.tqe_prev; (elm)->field.tqe_next = (listelm); *(listelm)->field.tqe_prev = (elm); (listelm)->field.tqe_prev = &(elm)->field.tqe_next; } while (0) 382 383 //#define TAILQ_REMOVE(head, elm, field) do { if (((elm)->field.tqe_next) != NULL) (elm)->field.tqe_next->field.tqe_prev = (elm)->field.tqe_prev; else (head)->tqh_last = (elm)->field.tqe_prev; *(elm)->field.tqe_prev = (elm)->field.tqe_next; _Q_INVALIDATE((elm)->field.tqe_prev); _Q_INVALIDATE((elm)->field.tqe_next); } while (0) 384 385 //#define TAILQ_REPLACE(head, elm, elm2, field) do { if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) (elm2)->field.tqe_next->field.tqe_prev = &(elm2)->field.tqe_next; else (head)->tqh_last = &(elm2)->field.tqe_next; (elm2)->field.tqe_prev = (elm)->field.tqe_prev; *(elm2)->field.tqe_prev = (elm2); _Q_INVALIDATE((elm)->field.tqe_prev); _Q_INVALIDATE((elm)->field.tqe_next); } while (0) 386 387 //#define TAILQ_CONCAT(head1, head2, field) do { if (!TAILQ_EMPTY(head2)) { *(head1)->tqh_last = (head2)->tqh_first; (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; (head1)->tqh_last = (head2)->tqh_last; TAILQ_INIT((head2)); } } while (0)