Path: blob/main/contrib/libevent/compat/sys/queue.h
48254 views
/* $OpenBSD: queue.h,v 1.16 2000/09/07 19:47:59 art Exp $ */1/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */23/*4* Copyright (c) 1991, 19935* The Regents of the University of California. All rights reserved.6*7* Redistribution and use in source and binary forms, with or without8* modification, are permitted provided that the following conditions9* are met:10* 1. Redistributions of source code must retain the above copyright11* notice, this list of conditions and the following disclaimer.12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15* 3. Neither the name of the University nor the names of its contributors16* may be used to endorse or promote products derived from this software17* without specific prior written permission.18*19* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND20* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE21* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE22* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE23* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL24* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS25* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)26* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT27* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY28* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF29* SUCH DAMAGE.30*31* @(#)queue.h 8.5 (Berkeley) 8/20/9432*/3334#ifndef SYS_QUEUE_H__35#define SYS_QUEUE_H__3637/*38* This file defines five types of data structures: singly-linked lists,39* lists, simple queues, tail queues, and circular queues.40*41*42* A singly-linked list is headed by a single forward pointer. The elements43* are singly linked for minimum space and pointer manipulation overhead at44* the expense of O(n) removal for arbitrary elements. New elements can be45* added to the list after an existing element or at the head of the list.46* Elements being removed from the head of the list should use the explicit47* macro for this purpose for optimum efficiency. A singly-linked list may48* only be traversed in the forward direction. Singly-linked lists are ideal49* for applications with large datasets and few or no removals or for50* implementing a LIFO queue.51*52* A list is headed by a single forward pointer (or an array of forward53* pointers for a hash table header). The elements are doubly linked54* so that an arbitrary element can be removed without a need to55* traverse the list. New elements can be added to the list before56* or after an existing element or at the head of the list. A list57* may only be traversed in the forward direction.58*59* A simple queue is headed by a pair of pointers, one the head of the60* list and the other to the tail of the list. The elements are singly61* linked to save space, so elements can only be removed from the62* head of the list. New elements can be added to the list before or after63* an existing element, at the head of the list, or at the end of the64* list. A simple queue may only be traversed in the forward direction.65*66* A tail queue is headed by a pair of pointers, one to the head of the67* list and the other to the tail of the list. The elements are doubly68* linked so that an arbitrary element can be removed without a need to69* traverse the list. New elements can be added to the list before or70* after an existing element, at the head of the list, or at the end of71* the list. A tail queue may be traversed in either direction.72*73* A circle queue is headed by a pair of pointers, one to the head of the74* list and the other to the tail of the list. The elements are doubly75* linked so that an arbitrary element can be removed without a need to76* traverse the list. New elements can be added to the list before or after77* an existing element, at the head of the list, or at the end of the list.78* A circle queue may be traversed in either direction, but has a more79* complex end of list detection.80*81* For details on the use of these macros, see the queue(3) manual page.82*/8384/*85* Singly-linked List definitions.86*/87#define SLIST_HEAD(name, type) \88struct name { \89struct type *slh_first; /* first element */ \90}9192#define SLIST_HEAD_INITIALIZER(head) \93{ NULL }9495#ifndef _WIN3296#define SLIST_ENTRY(type) \97struct { \98struct type *sle_next; /* next element */ \99}100#endif101102/*103* Singly-linked List access methods.104*/105#define SLIST_FIRST(head) ((head)->slh_first)106#define SLIST_END(head) NULL107#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))108#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)109110#define SLIST_FOREACH(var, head, field) \111for((var) = SLIST_FIRST(head); \112(var) != SLIST_END(head); \113(var) = SLIST_NEXT(var, field))114115/*116* Singly-linked List functions.117*/118#define SLIST_INIT(head) { \119SLIST_FIRST(head) = SLIST_END(head); \120}121122#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \123(elm)->field.sle_next = (slistelm)->field.sle_next; \124(slistelm)->field.sle_next = (elm); \125} while (0)126127#define SLIST_INSERT_HEAD(head, elm, field) do { \128(elm)->field.sle_next = (head)->slh_first; \129(head)->slh_first = (elm); \130} while (0)131132#define SLIST_REMOVE_HEAD(head, field) do { \133(head)->slh_first = (head)->slh_first->field.sle_next; \134} while (0)135136/*137* List definitions.138*/139#define LIST_HEAD(name, type) \140struct name { \141struct type *lh_first; /* first element */ \142}143144#define LIST_HEAD_INITIALIZER(head) \145{ NULL }146147#define LIST_ENTRY(type) \148struct { \149struct type *le_next; /* next element */ \150struct type **le_prev; /* address of previous next element */ \151}152153/*154* List access methods155*/156#define LIST_FIRST(head) ((head)->lh_first)157#define LIST_END(head) NULL158#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))159#define LIST_NEXT(elm, field) ((elm)->field.le_next)160161#define LIST_FOREACH(var, head, field) \162for((var) = LIST_FIRST(head); \163(var)!= LIST_END(head); \164(var) = LIST_NEXT(var, field))165166/*167* List functions.168*/169#define LIST_INIT(head) do { \170LIST_FIRST(head) = LIST_END(head); \171} while (0)172173#define LIST_INSERT_AFTER(listelm, elm, field) do { \174if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \175(listelm)->field.le_next->field.le_prev = \176&(elm)->field.le_next; \177(listelm)->field.le_next = (elm); \178(elm)->field.le_prev = &(listelm)->field.le_next; \179} while (0)180181#define LIST_INSERT_BEFORE(listelm, elm, field) do { \182(elm)->field.le_prev = (listelm)->field.le_prev; \183(elm)->field.le_next = (listelm); \184*(listelm)->field.le_prev = (elm); \185(listelm)->field.le_prev = &(elm)->field.le_next; \186} while (0)187188#define LIST_INSERT_HEAD(head, elm, field) do { \189if (((elm)->field.le_next = (head)->lh_first) != NULL) \190(head)->lh_first->field.le_prev = &(elm)->field.le_next;\191(head)->lh_first = (elm); \192(elm)->field.le_prev = &(head)->lh_first; \193} while (0)194195#define LIST_REMOVE(elm, field) do { \196if ((elm)->field.le_next != NULL) \197(elm)->field.le_next->field.le_prev = \198(elm)->field.le_prev; \199*(elm)->field.le_prev = (elm)->field.le_next; \200} while (0)201202#define LIST_REPLACE(elm, elm2, field) do { \203if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \204(elm2)->field.le_next->field.le_prev = \205&(elm2)->field.le_next; \206(elm2)->field.le_prev = (elm)->field.le_prev; \207*(elm2)->field.le_prev = (elm2); \208} while (0)209210/*211* Simple queue definitions.212*/213#define SIMPLEQ_HEAD(name, type) \214struct name { \215struct type *sqh_first; /* first element */ \216struct type **sqh_last; /* addr of last next element */ \217}218219#define SIMPLEQ_HEAD_INITIALIZER(head) \220{ NULL, &(head).sqh_first }221222#define SIMPLEQ_ENTRY(type) \223struct { \224struct type *sqe_next; /* next element */ \225}226227/*228* Simple queue access methods.229*/230#define SIMPLEQ_FIRST(head) ((head)->sqh_first)231#define SIMPLEQ_END(head) NULL232#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))233#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)234235#define SIMPLEQ_FOREACH(var, head, field) \236for((var) = SIMPLEQ_FIRST(head); \237(var) != SIMPLEQ_END(head); \238(var) = SIMPLEQ_NEXT(var, field))239240/*241* Simple queue functions.242*/243#define SIMPLEQ_INIT(head) do { \244(head)->sqh_first = NULL; \245(head)->sqh_last = &(head)->sqh_first; \246} while (0)247248#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \249if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \250(head)->sqh_last = &(elm)->field.sqe_next; \251(head)->sqh_first = (elm); \252} while (0)253254#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \255(elm)->field.sqe_next = NULL; \256*(head)->sqh_last = (elm); \257(head)->sqh_last = &(elm)->field.sqe_next; \258} while (0)259260#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \261if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\262(head)->sqh_last = &(elm)->field.sqe_next; \263(listelm)->field.sqe_next = (elm); \264} while (0)265266#define SIMPLEQ_REMOVE_HEAD(head, elm, field) do { \267if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) \268(head)->sqh_last = &(head)->sqh_first; \269} while (0)270271/*272* Tail queue definitions.273*/274#define TAILQ_HEAD(name, type) \275struct name { \276struct type *tqh_first; /* first element */ \277struct type **tqh_last; /* addr of last next element */ \278}279280#define TAILQ_HEAD_INITIALIZER(head) \281{ NULL, &(head).tqh_first }282283#define TAILQ_ENTRY(type) \284struct { \285struct type *tqe_next; /* next element */ \286struct type **tqe_prev; /* address of previous next element */ \287}288289/*290* tail queue access methods291*/292#define TAILQ_FIRST(head) ((head)->tqh_first)293#define TAILQ_END(head) NULL294#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)295#define TAILQ_LAST(head, headname) \296(*(((struct headname *)((head)->tqh_last))->tqh_last))297/* XXX */298#define TAILQ_PREV(elm, headname, field) \299(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))300#define TAILQ_EMPTY(head) \301(TAILQ_FIRST(head) == TAILQ_END(head))302303#define TAILQ_FOREACH(var, head, field) \304for((var) = TAILQ_FIRST(head); \305(var) != TAILQ_END(head); \306(var) = TAILQ_NEXT(var, field))307308#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \309for((var) = TAILQ_LAST(head, headname); \310(var) != TAILQ_END(head); \311(var) = TAILQ_PREV(var, headname, field))312313/*314* Tail queue functions.315*/316#define TAILQ_INIT(head) do { \317(head)->tqh_first = NULL; \318(head)->tqh_last = &(head)->tqh_first; \319} while (0)320321#define TAILQ_INSERT_HEAD(head, elm, field) do { \322if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \323(head)->tqh_first->field.tqe_prev = \324&(elm)->field.tqe_next; \325else \326(head)->tqh_last = &(elm)->field.tqe_next; \327(head)->tqh_first = (elm); \328(elm)->field.tqe_prev = &(head)->tqh_first; \329} while (0)330331#define TAILQ_INSERT_TAIL(head, elm, field) do { \332(elm)->field.tqe_next = NULL; \333(elm)->field.tqe_prev = (head)->tqh_last; \334*(head)->tqh_last = (elm); \335(head)->tqh_last = &(elm)->field.tqe_next; \336} while (0)337338#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \339if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\340(elm)->field.tqe_next->field.tqe_prev = \341&(elm)->field.tqe_next; \342else \343(head)->tqh_last = &(elm)->field.tqe_next; \344(listelm)->field.tqe_next = (elm); \345(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \346} while (0)347348#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \349(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \350(elm)->field.tqe_next = (listelm); \351*(listelm)->field.tqe_prev = (elm); \352(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \353} while (0)354355#define TAILQ_REMOVE(head, elm, field) do { \356if (((elm)->field.tqe_next) != NULL) \357(elm)->field.tqe_next->field.tqe_prev = \358(elm)->field.tqe_prev; \359else \360(head)->tqh_last = (elm)->field.tqe_prev; \361*(elm)->field.tqe_prev = (elm)->field.tqe_next; \362} while (0)363364#define TAILQ_REPLACE(head, elm, elm2, field) do { \365if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \366(elm2)->field.tqe_next->field.tqe_prev = \367&(elm2)->field.tqe_next; \368else \369(head)->tqh_last = &(elm2)->field.tqe_next; \370(elm2)->field.tqe_prev = (elm)->field.tqe_prev; \371*(elm2)->field.tqe_prev = (elm2); \372} while (0)373374/*375* Circular queue definitions.376*/377#define CIRCLEQ_HEAD(name, type) \378struct name { \379struct type *cqh_first; /* first element */ \380struct type *cqh_last; /* last element */ \381}382383#define CIRCLEQ_HEAD_INITIALIZER(head) \384{ CIRCLEQ_END(&head), CIRCLEQ_END(&head) }385386#define CIRCLEQ_ENTRY(type) \387struct { \388struct type *cqe_next; /* next element */ \389struct type *cqe_prev; /* previous element */ \390}391392/*393* Circular queue access methods394*/395#define CIRCLEQ_FIRST(head) ((head)->cqh_first)396#define CIRCLEQ_LAST(head) ((head)->cqh_last)397#define CIRCLEQ_END(head) ((void *)(head))398#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)399#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)400#define CIRCLEQ_EMPTY(head) \401(CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))402403#define CIRCLEQ_FOREACH(var, head, field) \404for((var) = CIRCLEQ_FIRST(head); \405(var) != CIRCLEQ_END(head); \406(var) = CIRCLEQ_NEXT(var, field))407408#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \409for((var) = CIRCLEQ_LAST(head); \410(var) != CIRCLEQ_END(head); \411(var) = CIRCLEQ_PREV(var, field))412413/*414* Circular queue functions.415*/416#define CIRCLEQ_INIT(head) do { \417(head)->cqh_first = CIRCLEQ_END(head); \418(head)->cqh_last = CIRCLEQ_END(head); \419} while (0)420421#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \422(elm)->field.cqe_next = (listelm)->field.cqe_next; \423(elm)->field.cqe_prev = (listelm); \424if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \425(head)->cqh_last = (elm); \426else \427(listelm)->field.cqe_next->field.cqe_prev = (elm); \428(listelm)->field.cqe_next = (elm); \429} while (0)430431#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \432(elm)->field.cqe_next = (listelm); \433(elm)->field.cqe_prev = (listelm)->field.cqe_prev; \434if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \435(head)->cqh_first = (elm); \436else \437(listelm)->field.cqe_prev->field.cqe_next = (elm); \438(listelm)->field.cqe_prev = (elm); \439} while (0)440441#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \442(elm)->field.cqe_next = (head)->cqh_first; \443(elm)->field.cqe_prev = CIRCLEQ_END(head); \444if ((head)->cqh_last == CIRCLEQ_END(head)) \445(head)->cqh_last = (elm); \446else \447(head)->cqh_first->field.cqe_prev = (elm); \448(head)->cqh_first = (elm); \449} while (0)450451#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \452(elm)->field.cqe_next = CIRCLEQ_END(head); \453(elm)->field.cqe_prev = (head)->cqh_last; \454if ((head)->cqh_first == CIRCLEQ_END(head)) \455(head)->cqh_first = (elm); \456else \457(head)->cqh_last->field.cqe_next = (elm); \458(head)->cqh_last = (elm); \459} while (0)460461#define CIRCLEQ_REMOVE(head, elm, field) do { \462if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \463(head)->cqh_last = (elm)->field.cqe_prev; \464else \465(elm)->field.cqe_next->field.cqe_prev = \466(elm)->field.cqe_prev; \467if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \468(head)->cqh_first = (elm)->field.cqe_next; \469else \470(elm)->field.cqe_prev->field.cqe_next = \471(elm)->field.cqe_next; \472} while (0)473474#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \475if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \476CIRCLEQ_END(head)) \477(head).cqh_last = (elm2); \478else \479(elm2)->field.cqe_next->field.cqe_prev = (elm2); \480if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \481CIRCLEQ_END(head)) \482(head).cqh_first = (elm2); \483else \484(elm2)->field.cqe_prev->field.cqe_next = (elm2); \485} while (0)486487#endif /* !SYS_QUEUE_H__ */488489490