Path: blob/main/crypto/krb5/src/include/k5-queue.h
34889 views
/*1* This is a copy of NetBSD's sys/queue.h, edited to use a different symbol for2* multiple inclusion protection and to suppress the include of <sys/null.h>.3*/45/* $NetBSD: queue.h,v 1.53 2011/11/19 22:51:31 tls Exp $ */67/*8* Copyright (c) 1991, 19939* The Regents of the University of California. All rights reserved.10*11* Redistribution and use in source and binary forms, with or without12* modification, are permitted provided that the following conditions13* are met:14* 1. Redistributions of source code must retain the above copyright15* notice, this list of conditions and the following disclaimer.16* 2. Redistributions in binary form must reproduce the above copyright17* notice, this list of conditions and the following disclaimer in the18* documentation and/or other materials provided with the distribution.19* 3. Neither the name of the University nor the names of its contributors20* may be used to endorse or promote products derived from this software21* without specific prior written permission.22*23* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND24* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE25* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE26* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE27* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL28* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS29* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)30* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT31* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY32* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF33* SUCH DAMAGE.34*35* @(#)queue.h 8.5 (Berkeley) 8/20/9436*/3738#ifndef K5_QUEUE_H39#define K5_QUEUE_H4041/* #include <sys/null.h> */4243/*44* This file defines five types of data structures: singly-linked lists,45* lists, simple queues, tail queues, and circular queues.46*47* A singly-linked list is headed by a single forward pointer. The48* elements are singly linked for minimum space and pointer manipulation49* overhead at the expense of O(n) removal for arbitrary elements. New50* elements can be added to the list after an existing element or at the51* head of the list. Elements being removed from the head of the list52* should use the explicit macro for this purpose for optimum53* efficiency. A singly-linked list may only be traversed in the forward54* direction. Singly-linked lists are ideal for applications with large55* datasets and few or no removals or for implementing a LIFO queue.56*57* A list is headed by a single forward pointer (or an array of forward58* pointers for a hash table header). The elements are doubly linked59* so that an arbitrary element can be removed without a need to60* traverse the list. New elements can be added to the list before61* or after an existing element or at the head of the list. A list62* may only be traversed in the forward direction.63*64* A simple queue is headed by a pair of pointers, one the head of the65* list and the other to the tail of the list. The elements are singly66* linked to save space, so elements can only be removed from the67* head of the list. New elements can be added to the list after68* an existing element, at the head of the list, or at the end of the69* 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 the72* list and the other to the tail of the list. The elements are doubly73* linked so that an arbitrary element can be removed without a need to74* traverse the list. New elements can be added to the list before or75* after an existing element, at the head of the list, or at the end of76* the list. A tail queue may be traversed in either direction.77*78* A circle queue is headed by a pair of pointers, one to the head of the79* list and the other to the tail of the list. The elements are doubly80* linked so that an arbitrary element can be removed without a need to81* traverse the list. New elements can be added to the list before or after82* an existing element, at the head of the list, or at the end of the list.83* A circle queue may be traversed in either direction, but has a more84* complex end of list detection.85*86* For details on the use of these macros, see the queue(3) manual page.87*/8889/*90* List definitions.91*/92#define K5_LIST_HEAD(name, type) \93struct name { \94struct type *lh_first; /* first element */ \95}9697#define K5_LIST_HEAD_INITIALIZER(head) \98{ NULL }99100#define K5_LIST_ENTRY(type) \101struct { \102struct type *le_next; /* next element */ \103struct type **le_prev; /* address of previous next element */ \104}105106/*107* List functions.108*/109#define K5_LIST_INIT(head) do { \110(head)->lh_first = NULL; \111} while (/*CONSTCOND*/0)112113#define K5_LIST_INSERT_AFTER(listelm, elm, field) do { \114if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \115(listelm)->field.le_next->field.le_prev = \116&(elm)->field.le_next; \117(listelm)->field.le_next = (elm); \118(elm)->field.le_prev = &(listelm)->field.le_next; \119} while (/*CONSTCOND*/0)120121#define K5_LIST_INSERT_BEFORE(listelm, elm, field) do { \122(elm)->field.le_prev = (listelm)->field.le_prev; \123(elm)->field.le_next = (listelm); \124*(listelm)->field.le_prev = (elm); \125(listelm)->field.le_prev = &(elm)->field.le_next; \126} while (/*CONSTCOND*/0)127128#define K5_LIST_INSERT_HEAD(head, elm, field) do { \129if (((elm)->field.le_next = (head)->lh_first) != NULL) \130(head)->lh_first->field.le_prev = &(elm)->field.le_next;\131(head)->lh_first = (elm); \132(elm)->field.le_prev = &(head)->lh_first; \133} while (/*CONSTCOND*/0)134135#define K5_LIST_REMOVE(elm, field) do { \136if ((elm)->field.le_next != NULL) \137(elm)->field.le_next->field.le_prev = \138(elm)->field.le_prev; \139*(elm)->field.le_prev = (elm)->field.le_next; \140} while (/*CONSTCOND*/0)141142#define K5_LIST_FOREACH(var, head, field) \143for ((var) = ((head)->lh_first); \144(var); \145(var) = ((var)->field.le_next))146147#define K5_LIST_FOREACH_SAFE(var, head, field, tvar) \148for ((var) = K5_LIST_FIRST((head)); \149(var) && ((tvar) = K5_LIST_NEXT((var), field), 1); \150(var) = (tvar))151/*152* List access methods.153*/154#define K5_LIST_EMPTY(head) ((head)->lh_first == NULL)155#define K5_LIST_FIRST(head) ((head)->lh_first)156#define K5_LIST_NEXT(elm, field) ((elm)->field.le_next)157158159/*160* Singly-linked List definitions.161*/162#define K5_SLIST_HEAD(name, type) \163struct name { \164struct type *slh_first; /* first element */ \165}166167#define K5_SLIST_HEAD_INITIALIZER(head) \168{ NULL }169170#define K5_SLIST_ENTRY(type) \171struct { \172struct type *sle_next; /* next element */ \173}174175/*176* Singly-linked List functions.177*/178#define K5_SLIST_INIT(head) do { \179(head)->slh_first = NULL; \180} while (/*CONSTCOND*/0)181182#define K5_SLIST_INSERT_AFTER(slistelm, elm, field) do { \183(elm)->field.sle_next = (slistelm)->field.sle_next; \184(slistelm)->field.sle_next = (elm); \185} while (/*CONSTCOND*/0)186187#define K5_SLIST_INSERT_HEAD(head, elm, field) do { \188(elm)->field.sle_next = (head)->slh_first; \189(head)->slh_first = (elm); \190} while (/*CONSTCOND*/0)191192#define K5_SLIST_REMOVE_HEAD(head, field) do { \193(head)->slh_first = (head)->slh_first->field.sle_next; \194} while (/*CONSTCOND*/0)195196#define K5_SLIST_REMOVE(head, elm, type, field) do { \197if ((head)->slh_first == (elm)) { \198K5_SLIST_REMOVE_HEAD((head), field); \199} \200else { \201struct type *curelm = (head)->slh_first; \202while(curelm->field.sle_next != (elm)) \203curelm = curelm->field.sle_next; \204curelm->field.sle_next = \205curelm->field.sle_next->field.sle_next; \206} \207} while (/*CONSTCOND*/0)208209#define K5_SLIST_REMOVE_AFTER(slistelm, field) do { \210(slistelm)->field.sle_next = \211K5_SLIST_NEXT(K5_SLIST_NEXT((slistelm), field), field); \212} while (/*CONSTCOND*/0)213214#define K5_SLIST_FOREACH(var, head, field) \215for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)216217#define K5_SLIST_FOREACH_SAFE(var, head, field, tvar) \218for ((var) = K5_SLIST_FIRST((head)); \219(var) && ((tvar) = K5_SLIST_NEXT((var), field), 1); \220(var) = (tvar))221222/*223* Singly-linked List access methods.224*/225#define K5_SLIST_EMPTY(head) ((head)->slh_first == NULL)226#define K5_SLIST_FIRST(head) ((head)->slh_first)227#define K5_SLIST_NEXT(elm, field) ((elm)->field.sle_next)228229230/*231* Singly-linked Tail queue declarations.232*/233#define K5_STAILQ_HEAD(name, type) \234struct name { \235struct type *stqh_first; /* first element */ \236struct type **stqh_last; /* addr of last next element */ \237}238239#define K5_STAILQ_HEAD_INITIALIZER(head) \240{ NULL, &(head).stqh_first }241242#define K5_STAILQ_ENTRY(type) \243struct { \244struct type *stqe_next; /* next element */ \245}246247/*248* Singly-linked Tail queue functions.249*/250#define K5_STAILQ_INIT(head) do { \251(head)->stqh_first = NULL; \252(head)->stqh_last = &(head)->stqh_first; \253} while (/*CONSTCOND*/0)254255#define K5_STAILQ_INSERT_HEAD(head, elm, field) do { \256if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \257(head)->stqh_last = &(elm)->field.stqe_next; \258(head)->stqh_first = (elm); \259} while (/*CONSTCOND*/0)260261#define K5_STAILQ_INSERT_TAIL(head, elm, field) do { \262(elm)->field.stqe_next = NULL; \263*(head)->stqh_last = (elm); \264(head)->stqh_last = &(elm)->field.stqe_next; \265} while (/*CONSTCOND*/0)266267#define K5_STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \268if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\269(head)->stqh_last = &(elm)->field.stqe_next; \270(listelm)->field.stqe_next = (elm); \271} while (/*CONSTCOND*/0)272273#define K5_STAILQ_REMOVE_HEAD(head, field) do { \274if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \275(head)->stqh_last = &(head)->stqh_first; \276} while (/*CONSTCOND*/0)277278#define K5_STAILQ_REMOVE(head, elm, type, field) do { \279if ((head)->stqh_first == (elm)) { \280K5_STAILQ_REMOVE_HEAD((head), field); \281} else { \282struct type *curelm = (head)->stqh_first; \283while (curelm->field.stqe_next != (elm)) \284curelm = curelm->field.stqe_next; \285if ((curelm->field.stqe_next = \286curelm->field.stqe_next->field.stqe_next) == NULL) \287(head)->stqh_last = &(curelm)->field.stqe_next; \288} \289} while (/*CONSTCOND*/0)290291#define K5_STAILQ_FOREACH(var, head, field) \292for ((var) = ((head)->stqh_first); \293(var); \294(var) = ((var)->field.stqe_next))295296#define K5_STAILQ_FOREACH_SAFE(var, head, field, tvar) \297for ((var) = K5_STAILQ_FIRST((head)); \298(var) && ((tvar) = K5_STAILQ_NEXT((var), field), 1); \299(var) = (tvar))300301#define K5_STAILQ_CONCAT(head1, head2) do { \302if (!K5_STAILQ_EMPTY((head2))) { \303*(head1)->stqh_last = (head2)->stqh_first; \304(head1)->stqh_last = (head2)->stqh_last; \305K5_STAILQ_INIT((head2)); \306} \307} while (/*CONSTCOND*/0)308309#define K5_STAILQ_LAST(head, type, field) \310(K5_STAILQ_EMPTY((head)) ? \311NULL : \312((struct type *)(void *) \313((char *)((head)->stqh_last) - offsetof(struct type, field))))314315/*316* Singly-linked Tail queue access methods.317*/318#define K5_STAILQ_EMPTY(head) ((head)->stqh_first == NULL)319#define K5_STAILQ_FIRST(head) ((head)->stqh_first)320#define K5_STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)321322323/*324* Simple queue definitions.325*/326#define K5_SIMPLEQ_HEAD(name, type) \327struct name { \328struct type *sqh_first; /* first element */ \329struct type **sqh_last; /* addr of last next element */ \330}331332#define K5_SIMPLEQ_HEAD_INITIALIZER(head) \333{ NULL, &(head).sqh_first }334335#define K5_SIMPLEQ_ENTRY(type) \336struct { \337struct type *sqe_next; /* next element */ \338}339340/*341* Simple queue functions.342*/343#define K5_SIMPLEQ_INIT(head) do { \344(head)->sqh_first = NULL; \345(head)->sqh_last = &(head)->sqh_first; \346} while (/*CONSTCOND*/0)347348#define K5_SIMPLEQ_INSERT_HEAD(head, elm, field) do { \349if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \350(head)->sqh_last = &(elm)->field.sqe_next; \351(head)->sqh_first = (elm); \352} while (/*CONSTCOND*/0)353354#define K5_SIMPLEQ_INSERT_TAIL(head, elm, field) do { \355(elm)->field.sqe_next = NULL; \356*(head)->sqh_last = (elm); \357(head)->sqh_last = &(elm)->field.sqe_next; \358} while (/*CONSTCOND*/0)359360#define K5_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \361if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\362(head)->sqh_last = &(elm)->field.sqe_next; \363(listelm)->field.sqe_next = (elm); \364} while (/*CONSTCOND*/0)365366#define K5_SIMPLEQ_REMOVE_HEAD(head, field) do { \367if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \368(head)->sqh_last = &(head)->sqh_first; \369} while (/*CONSTCOND*/0)370371#define K5_SIMPLEQ_REMOVE(head, elm, type, field) do { \372if ((head)->sqh_first == (elm)) { \373K5_SIMPLEQ_REMOVE_HEAD((head), field); \374} else { \375struct type *curelm = (head)->sqh_first; \376while (curelm->field.sqe_next != (elm)) \377curelm = curelm->field.sqe_next; \378if ((curelm->field.sqe_next = \379curelm->field.sqe_next->field.sqe_next) == NULL) \380(head)->sqh_last = &(curelm)->field.sqe_next; \381} \382} while (/*CONSTCOND*/0)383384#define K5_SIMPLEQ_FOREACH(var, head, field) \385for ((var) = ((head)->sqh_first); \386(var); \387(var) = ((var)->field.sqe_next))388389#define K5_SIMPLEQ_FOREACH_SAFE(var, head, field, next) \390for ((var) = ((head)->sqh_first); \391(var) && ((next = ((var)->field.sqe_next)), 1); \392(var) = (next))393394#define K5_SIMPLEQ_CONCAT(head1, head2) do { \395if (!K5_SIMPLEQ_EMPTY((head2))) { \396*(head1)->sqh_last = (head2)->sqh_first; \397(head1)->sqh_last = (head2)->sqh_last; \398K5_SIMPLEQ_INIT((head2)); \399} \400} while (/*CONSTCOND*/0)401402#define K5_SIMPLEQ_LAST(head, type, field) \403(K5_SIMPLEQ_EMPTY((head)) ? \404NULL : \405((struct type *)(void *) \406((char *)((head)->sqh_last) - offsetof(struct type, field))))407408/*409* Simple queue access methods.410*/411#define K5_SIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL)412#define K5_SIMPLEQ_FIRST(head) ((head)->sqh_first)413#define K5_SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)414415416/*417* Tail queue definitions.418*/419#define _K5_TAILQ_HEAD(name, type, qual) \420struct name { \421qual type *tqh_first; /* first element */ \422qual type *qual *tqh_last; /* addr of last next element */ \423}424#define K5_TAILQ_HEAD(name, type) _K5_TAILQ_HEAD(name, struct type,)425426#define K5_TAILQ_HEAD_INITIALIZER(head) \427{ NULL, &(head).tqh_first }428429#define _K5_TAILQ_ENTRY(type, qual) \430struct { \431qual type *tqe_next; /* next element */ \432qual type *qual *tqe_prev; /* address of previous next element */\433}434#define K5_TAILQ_ENTRY(type) _K5_TAILQ_ENTRY(struct type,)435436/*437* Tail queue functions.438*/439#define K5_TAILQ_INIT(head) do { \440(head)->tqh_first = NULL; \441(head)->tqh_last = &(head)->tqh_first; \442} while (/*CONSTCOND*/0)443444#define K5_TAILQ_INSERT_HEAD(head, elm, field) do { \445if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \446(head)->tqh_first->field.tqe_prev = \447&(elm)->field.tqe_next; \448else \449(head)->tqh_last = &(elm)->field.tqe_next; \450(head)->tqh_first = (elm); \451(elm)->field.tqe_prev = &(head)->tqh_first; \452} while (/*CONSTCOND*/0)453454#define K5_TAILQ_INSERT_TAIL(head, elm, field) do { \455(elm)->field.tqe_next = NULL; \456(elm)->field.tqe_prev = (head)->tqh_last; \457*(head)->tqh_last = (elm); \458(head)->tqh_last = &(elm)->field.tqe_next; \459} while (/*CONSTCOND*/0)460461#define K5_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \462if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\463(elm)->field.tqe_next->field.tqe_prev = \464&(elm)->field.tqe_next; \465else \466(head)->tqh_last = &(elm)->field.tqe_next; \467(listelm)->field.tqe_next = (elm); \468(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \469} while (/*CONSTCOND*/0)470471#define K5_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \472(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \473(elm)->field.tqe_next = (listelm); \474*(listelm)->field.tqe_prev = (elm); \475(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \476} while (/*CONSTCOND*/0)477478#define K5_TAILQ_REMOVE(head, elm, field) do { \479if (((elm)->field.tqe_next) != NULL) \480(elm)->field.tqe_next->field.tqe_prev = \481(elm)->field.tqe_prev; \482else \483(head)->tqh_last = (elm)->field.tqe_prev; \484*(elm)->field.tqe_prev = (elm)->field.tqe_next; \485} while (/*CONSTCOND*/0)486487#define K5_TAILQ_FOREACH(var, head, field) \488for ((var) = ((head)->tqh_first); \489(var); \490(var) = ((var)->field.tqe_next))491492#define K5_TAILQ_FOREACH_SAFE(var, head, field, next) \493for ((var) = ((head)->tqh_first); \494(var) != NULL && ((next) = K5_TAILQ_NEXT(var, field), 1); \495(var) = (next))496497#define K5_TAILQ_FOREACH_REVERSE(var, head, headname, field) \498for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \499(var); \500(var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))501502#define K5_TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, prev) \503for ((var) = K5_TAILQ_LAST((head), headname); \504(var) && ((prev) = K5_TAILQ_PREV((var), headname, field), 1);\505(var) = (prev))506507#define K5_TAILQ_CONCAT(head1, head2, field) do { \508if (!K5_TAILQ_EMPTY(head2)) { \509*(head1)->tqh_last = (head2)->tqh_first; \510(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \511(head1)->tqh_last = (head2)->tqh_last; \512K5_TAILQ_INIT((head2)); \513} \514} while (/*CONSTCOND*/0)515516/*517* Tail queue access methods.518*/519#define K5_TAILQ_EMPTY(head) ((head)->tqh_first == NULL)520#define K5_TAILQ_FIRST(head) ((head)->tqh_first)521#define K5_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)522523#define K5_TAILQ_LAST(head, headname) \524(*(((struct headname *)((head)->tqh_last))->tqh_last))525#define K5_TAILQ_PREV(elm, headname, field) \526(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))527528529/*530* Circular queue definitions.531*/532#define K5_CIRCLEQ_HEAD(name, type) \533struct name { \534struct type *cqh_first; /* first element */ \535struct type *cqh_last; /* last element */ \536}537538#define K5_CIRCLEQ_HEAD_INITIALIZER(head) \539{ (void *)&head, (void *)&head }540541#define K5_CIRCLEQ_ENTRY(type) \542struct { \543struct type *cqe_next; /* next element */ \544struct type *cqe_prev; /* previous element */ \545}546547/*548* Circular queue functions.549*/550#define K5_CIRCLEQ_INIT(head) do { \551(head)->cqh_first = (void *)(head); \552(head)->cqh_last = (void *)(head); \553} while (/*CONSTCOND*/0)554555#define K5_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \556(elm)->field.cqe_next = (listelm)->field.cqe_next; \557(elm)->field.cqe_prev = (listelm); \558if ((listelm)->field.cqe_next == (void *)(head)) \559(head)->cqh_last = (elm); \560else \561(listelm)->field.cqe_next->field.cqe_prev = (elm); \562(listelm)->field.cqe_next = (elm); \563} while (/*CONSTCOND*/0)564565#define K5_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \566(elm)->field.cqe_next = (listelm); \567(elm)->field.cqe_prev = (listelm)->field.cqe_prev; \568if ((listelm)->field.cqe_prev == (void *)(head)) \569(head)->cqh_first = (elm); \570else \571(listelm)->field.cqe_prev->field.cqe_next = (elm); \572(listelm)->field.cqe_prev = (elm); \573} while (/*CONSTCOND*/0)574575#define K5_CIRCLEQ_INSERT_HEAD(head, elm, field) do { \576(elm)->field.cqe_next = (head)->cqh_first; \577(elm)->field.cqe_prev = (void *)(head); \578if ((head)->cqh_last == (void *)(head)) \579(head)->cqh_last = (elm); \580else \581(head)->cqh_first->field.cqe_prev = (elm); \582(head)->cqh_first = (elm); \583} while (/*CONSTCOND*/0)584585#define K5_CIRCLEQ_INSERT_TAIL(head, elm, field) do { \586(elm)->field.cqe_next = (void *)(head); \587(elm)->field.cqe_prev = (head)->cqh_last; \588if ((head)->cqh_first == (void *)(head)) \589(head)->cqh_first = (elm); \590else \591(head)->cqh_last->field.cqe_next = (elm); \592(head)->cqh_last = (elm); \593} while (/*CONSTCOND*/0)594595#define K5_CIRCLEQ_REMOVE(head, elm, field) do { \596if ((elm)->field.cqe_next == (void *)(head)) \597(head)->cqh_last = (elm)->field.cqe_prev; \598else \599(elm)->field.cqe_next->field.cqe_prev = \600(elm)->field.cqe_prev; \601if ((elm)->field.cqe_prev == (void *)(head)) \602(head)->cqh_first = (elm)->field.cqe_next; \603else \604(elm)->field.cqe_prev->field.cqe_next = \605(elm)->field.cqe_next; \606} while (/*CONSTCOND*/0)607608#define K5_CIRCLEQ_FOREACH(var, head, field) \609for ((var) = ((head)->cqh_first); \610(var) != (const void *)(head); \611(var) = ((var)->field.cqe_next))612613#define K5_CIRCLEQ_FOREACH_REVERSE(var, head, field) \614for ((var) = ((head)->cqh_last); \615(var) != (const void *)(head); \616(var) = ((var)->field.cqe_prev))617618/*619* Circular queue access methods.620*/621#define K5_CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))622#define K5_CIRCLEQ_FIRST(head) ((head)->cqh_first)623#define K5_CIRCLEQ_LAST(head) ((head)->cqh_last)624#define K5_CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)625#define K5_CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)626627#define K5_CIRCLEQ_LOOP_NEXT(head, elm, field) \628(((elm)->field.cqe_next == (void *)(head)) \629? ((head)->cqh_first) \630: (elm->field.cqe_next))631#define K5_CIRCLEQ_LOOP_PREV(head, elm, field) \632(((elm)->field.cqe_prev == (void *)(head)) \633? ((head)->cqh_last) \634: (elm->field.cqe_prev))635636#endif /* !K5_QUEUE_H */637638639