From: Dave Hart Date: Wed, 20 Jul 2011 19:37:50 +0000 (+0000) Subject: Backport latest ntp_lists.h from ntp-dev, remove redundant () in X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d76b9d8339ef49958ec4c49927be11fd7e30f3be;p=thirdparty%2Fntp.git Backport latest ntp_lists.h from ntp-dev, remove redundant () in UNLINK_EXPR_SLIST(). bk: 4e272e8e8Do7dCR1nabhG1T2b7bt0g --- diff --git a/include/ntp_lists.h b/include/ntp_lists.h index 6079b83a92..2b6e616965 100644 --- a/include/ntp_lists.h +++ b/include/ntp_lists.h @@ -20,7 +20,8 @@ * add entry at head * * LINK_TAIL_SLIST(listhead, pentry, nextlink, entrytype) - * add entry at tail + * add entry at tail. This is O(n), if this is a common + * operation the FIFO template may be more appropriate. * * LINK_SORT_SLIST(listhead, pentry, beforecur, nextlink, entrytype) * add entry in sorted order. beforecur is an expression comparing @@ -46,6 +47,52 @@ * punlinked is pointed to the removed entry or NULL if none * satisfy expr. * + * FIFO: singly-linked lists plus tail pointer + * =========================================== + * + * This is the same as FreeBSD's sys/queue.h STAILQ -- a singly-linked + * list implementation with tail-pointer maintenance, so that adding + * at the tail for first-in, first-out access is O(1). + * + * DECL_FIFO_ANCHOR(entrytype) + * provides the type specification portion of the declaration for + * a variable to refer to a FIFO queue (similar to listhead). The + * anchor contains the head and indirect tail pointers. Example: + * + * #include "ntp_lists.h" + * + * typedef struct myentry_tag myentry; + * struct myentry_tag { + * myentry *next_link; + * ... + * }; + * + * DECL_FIFO_ANCHOR(myentry) my_fifo; + * + * void somefunc(myentry *pentry) + * { + * LINK_FIFO(my_fifo, pentry, next_link); + * } + * + * If DECL_FIFO_ANCHOR is used with stack or heap storage, it + * should be initialized to NULL pointers using a = { NULL }; + * initializer or memset. + * + * HEAD_FIFO(anchor) + * TAIL_FIFO(anchor) + * Pointer to first/last entry, NULL if FIFO is empty. + * + * LINK_FIFO(anchor, pentry, nextlink) + * add entry at tail. + * + * UNLINK_FIFO(punlinked, anchor, nextlink) + * unlink head entry and point punlinked to it, or set punlinked + * to NULL if the list is empty. + * + * CONCAT_FIFO(q1, q2, nextlink) + * empty fifoq q2 moving its nodes to q1 following q1's existing + * nodes. + * * DLIST: doubly-linked lists * ========================== * @@ -59,16 +106,30 @@ #ifndef NTP_LISTS_H #define NTP_LISTS_H -#ifndef TRUE -# define TRUE 1 -# define NTP_LISTS_UNDEF_TRUE +#include "ntp_types.h" /* TRUE and FALSE */ +#include "ntp_assert.h" + +#ifdef DEBUG +# define NTP_DEBUG_LISTS_H +#endif + +/* + * If list debugging is not enabled, save a little time by not clearing + * an entry's link pointer when it is unlinked, as the stale pointer + * is harmless as long as it is ignored when the entry is not in a + * list. + */ +#ifndef NTP_DEBUG_LISTS_H +#define MAYBE_Z_LISTS(p) do { } while (FALSE) +#else +#define MAYBE_Z_LISTS(p) (p) = NULL #endif #define LINK_SLIST(listhead, pentry, nextlink) \ do { \ (pentry)->nextlink = (listhead); \ (listhead) = (pentry); \ -} while (0) +} while (FALSE) #define LINK_TAIL_SLIST(listhead, pentry, nextlink, entrytype) \ do { \ @@ -80,7 +141,7 @@ do { \ \ (pentry)->nextlink = NULL; \ *pptail = (pentry); \ -} while (0) +} while (FALSE) #define LINK_SORT_SLIST_CURRENT() (*ppentry) #define L_S_S_CUR() LINK_SORT_SLIST_CURRENT() @@ -91,8 +152,8 @@ do { \ entrytype **ppentry; \ \ ppentry = &(listhead); \ - while (*ppentry != NULL) { \ - if (beforecur) { \ + while (TRUE) { \ + if (NULL == *ppentry || (beforecur)) { \ (pentry)->nextlink = *ppentry; \ *ppentry = (pentry); \ break; \ @@ -104,16 +165,16 @@ do { \ break; \ } \ } \ -} while (0) +} while (FALSE) #define UNLINK_HEAD_SLIST(punlinked, listhead, nextlink) \ do { \ (punlinked) = (listhead); \ if (NULL != (punlinked)) { \ (listhead) = (punlinked)->nextlink; \ - (punlinked)->nextlink = NULL; \ + MAYBE_Z_LISTS((punlinked)->nextlink); \ } \ -} while (0) +} while (FALSE) #define UNLINK_EXPR_SLIST_CURRENT() (*ppentry) #define U_E_S_CUR() UNLINK_EXPR_SLIST_CURRENT() @@ -126,10 +187,10 @@ do { \ ppentry = &(listhead); \ \ while (!(expr)) \ - if ((*ppentry) != NULL && \ + if (*ppentry != NULL && \ (*ppentry)->nextlink != NULL) { \ ppentry = &((*ppentry)->nextlink); \ - } else { \ + } else { \ ppentry = NULL; \ break; \ } \ @@ -137,10 +198,11 @@ do { \ if (ppentry != NULL) { \ (punlinked) = *ppentry; \ *ppentry = (punlinked)->nextlink; \ - (punlinked)->nextlink = NULL; \ - } else \ + MAYBE_Z_LISTS((punlinked)->nextlink); \ + } else { \ (punlinked) = NULL; \ -} while (0) + } \ +} while (FALSE) #define UNLINK_SLIST(punlinked, listhead, ptounlink, nextlink, \ entrytype) \ @@ -157,7 +219,135 @@ do { \ NTP_INSIST(pentry != pentry->nextlink); \ NTP_INSIST((listhead) != pentry->nextlink); \ } \ -} while (0) +} while (FALSE) + +/* + * FIFO + */ + +#define DECL_FIFO_ANCHOR(entrytype) \ +struct { \ + entrytype * phead; /* NULL if list empty */ \ + entrytype ** pptail; /* NULL if list empty */ \ +} + +#define HEAD_FIFO(anchor) ((anchor).phead) +#define TAIL_FIFO(anchor) ((NULL == (anchor).pptail) \ + ? NULL \ + : *((anchor).pptail)) + +/* + * For DEBUG builds only, verify both or neither of the anchor pointers + * are NULL with each operation. + */ +#if !defined(NTP_DEBUG_LISTS_H) +#define CHECK_FIFO_CONSISTENCY(anchor) do { } while (FALSE) +#else +#define CHECK_FIFO_CONSISTENCY(anchor) \ + check_gen_fifo_consistency(&(anchor)) +void check_gen_fifo_consistency(void *fifo); +#endif + +/* + * generic FIFO element used to access any FIFO where each element + * begins with the link pointer + */ +typedef struct gen_node_tag gen_node; +struct gen_node_tag { + gen_node * link; +}; + +/* generic FIFO */ +typedef DECL_FIFO_ANCHOR(gen_node) gen_fifo; + + +#define LINK_FIFO(anchor, pentry, nextlink) \ +do { \ + CHECK_FIFO_CONSISTENCY(anchor); \ + \ + (pentry)->nextlink = NULL; \ + if (NULL != (anchor).pptail) { \ + (*((anchor).pptail))->nextlink = (pentry); \ + (anchor).pptail = \ + &(*((anchor).pptail))->nextlink; \ + } else { \ + (anchor).phead = (pentry); \ + (anchor).pptail = &(anchor).phead; \ + } \ + \ + CHECK_FIFO_CONSISTENCY(anchor); \ +} while (FALSE) + +#define UNLINK_FIFO(punlinked, anchor, nextlink) \ +do { \ + CHECK_FIFO_CONSISTENCY(anchor); \ + \ + (punlinked) = (anchor).phead; \ + if (NULL != (punlinked)) { \ + (anchor).phead = (punlinked)->nextlink; \ + if (NULL == (anchor).phead) \ + (anchor).pptail = NULL; \ + else if ((anchor).pptail == \ + &(punlinked)->nextlink) \ + (anchor).pptail = &(anchor).phead; \ + MAYBE_Z_LISTS((punlinked)->nextlink); \ + CHECK_FIFO_CONSISTENCY(anchor); \ + } \ +} while (FALSE) + +#define UNLINK_MID_FIFO(punlinked, anchor, tounlink, nextlink, \ + entrytype) \ +do { \ + entrytype **ppentry; \ + \ + CHECK_FIFO_CONSISTENCY(anchor); \ + \ + ppentry = &(anchor).phead; \ + \ + while ((tounlink) != *ppentry) \ + if ((*ppentry)->nextlink != NULL) { \ + ppentry = &((*ppentry)->nextlink); \ + } else { \ + ppentry = NULL; \ + break; \ + } \ + \ + if (ppentry != NULL) { \ + (punlinked) = *ppentry; \ + *ppentry = (punlinked)->nextlink; \ + if (NULL == *ppentry) \ + (anchor).pptail = NULL; \ + else if ((anchor).pptail == \ + &(punlinked)->nextlink) \ + (anchor).pptail = &(anchor).phead; \ + MAYBE_Z_LISTS((punlinked)->nextlink); \ + CHECK_FIFO_CONSISTENCY(anchor); \ + } else { \ + (punlinked) = NULL; \ + } \ +} while (FALSE) + +#define CONCAT_FIFO(f1, f2, nextlink) \ +do { \ + CHECK_FIFO_CONSISTENCY(f1); \ + CHECK_FIFO_CONSISTENCY(f2); \ + \ + if ((f2).pptail != NULL) { \ + if ((f1).pptail != NULL) { \ + (*(f1).pptail)->nextlink = (f2).phead; \ + if ((f2).pptail == &(f2).phead) \ + (f1).pptail = \ + &(*(f1).pptail)->nextlink; \ + else \ + (f1).pptail = (f2).pptail; \ + CHECK_FIFO_CONSISTENCY(f1); \ + } else { \ + (f1) = (f2); \ + } \ + MAYBE_Z_LISTS((f2).phead); \ + MAYBE_Z_LISTS((f2).pptail); \ + } \ +} while (FALSE) /* * DLIST @@ -172,7 +362,7 @@ struct { \ do { \ (listhead).link.f = &(listhead); \ (listhead).link.b = &(listhead); \ -} while (0) +} while (FALSE) #define HEAD_DLIST(listhead, link) \ ( \ @@ -208,7 +398,7 @@ do { \ (pentry)->link.b = &(listhead); \ (listhead).link.f->link.b = (pentry); \ (listhead).link.f = (pentry); \ -} while (0) +} while (FALSE) #define LINK_TAIL_DLIST(listhead, pentry, link) \ do { \ @@ -216,15 +406,15 @@ do { \ (pentry)->link.f = &(listhead); \ (listhead).link.b->link.f = (pentry); \ (listhead).link.b = (pentry); \ -} while (0) +} while (FALSE) #define UNLINK_DLIST(ptounlink, link) \ do { \ (ptounlink)->link.b->link.f = (ptounlink)->link.f; \ (ptounlink)->link.f->link.b = (ptounlink)->link.b; \ - (ptounlink)->link.b = NULL; \ - (ptounlink)->link.f = NULL; \ -} while (0) + MAYBE_Z_LISTS((ptounlink)->link.b); \ + MAYBE_Z_LISTS((ptounlink)->link.f); \ +} while (FALSE) #define ITER_DLIST_BEGIN(listhead, iter, link, entrytype) \ { \ @@ -250,9 +440,4 @@ do { \ } \ } - -#ifdef NTP_LISTS_UNDEF_TRUE -# undef TRUE -#endif - #endif /* NTP_LISTS_H */