]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
Backport latest ntp_lists.h from ntp-dev, remove redundant () in
authorDave Hart <hart@ntp.org>
Wed, 20 Jul 2011 19:37:50 +0000 (19:37 +0000)
committerDave Hart <hart@ntp.org>
Wed, 20 Jul 2011 19:37:50 +0000 (19:37 +0000)
  UNLINK_EXPR_SLIST().

bk: 4e272e8e8Do7dCR1nabhG1T2b7bt0g

include/ntp_lists.h

index 6079b83a926c946b0dc7340e2432d9dcd5ad9b50..2b6e616965a7c8cf0a9bfaa096fa6267e608f00f 100644 (file)
@@ -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
  *     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
  * ==========================
  *
 #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 */