Annotation of embedaddon/ntp/include/ntp_lists.h, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * ntp_lists.h - linked lists common code
                      3:  *
                      4:  * SLIST: singly-linked lists
                      5:  * ==========================
                      6:  *
                      7:  * These macros implement a simple singly-linked list template.  Both
                      8:  * the listhead and per-entry next fields are declared as pointers to
                      9:  * the list entry struct type.  Initialization to NULL is typically
                     10:  * implicit (for globals and statics) or handled by zeroing of the
                     11:  * containing structure.
                     12:  *
                     13:  * The name of the next link field is passed as an argument to allow
                     14:  * membership in several lists at once using multiple next link fields.
                     15:  *
                     16:  * When possible, placing the link field first in the entry structure
                     17:  * allows slightly smaller code to be generated on some platforms.
                     18:  *
                     19:  * LINK_SLIST(listhead, pentry, nextlink)
                     20:  *     add entry at head
                     21:  *
                     22:  * LINK_TAIL_SLIST(listhead, pentry, nextlink, entrytype)
                     23:  *     add entry at tail.  This is O(n), if this is a common
                     24:  *     operation the FIFO template may be more appropriate.
                     25:  *
                     26:  * LINK_SORT_SLIST(listhead, pentry, beforecur, nextlink, entrytype)
                     27:  *     add entry in sorted order.  beforecur is an expression comparing
                     28:  *     pentry with the current list entry.  The current entry can be
                     29:  *     referenced within beforecur as L_S_S_CUR(), which is short for
                     30:  *     LINK_SORT_SLIST_CUR().  beforecur is nonzero if pentry sorts
                     31:  *     before L_S_S_CUR().
                     32:  *
                     33:  * UNLINK_HEAD_SLIST(punlinked, listhead, nextlink)
                     34:  *     unlink first entry and point punlinked to it, or set punlinked
                     35:  *     to NULL if the list is empty.
                     36:  *
                     37:  * UNLINK_SLIST(punlinked, listhead, ptounlink, nextlink, entrytype)
                     38:  *     unlink entry pointed to by ptounlink.  punlinked is set to NULL
                     39:  *     if the entry is not found on the list, otherwise it is set to
                     40:  *     ptounlink.
                     41:  *
                     42:  * UNLINK_EXPR_SLIST(punlinked, listhead, expr, nextlink, entrytype)
                     43:  *     unlink entry where expression expr is nonzero.  expr can refer
                     44:  *     to the entry being tested using UNLINK_EXPR_SLIST_CURRENT(),
                     45:  *     alias U_E_S_CUR().  See the implementation of UNLINK_SLIST()
                     46:  *     below for an example. U_E_S_CUR() is NULL iff the list is empty.
                     47:  *     punlinked is pointed to the removed entry or NULL if none
                     48:  *     satisfy expr.
                     49:  *
                     50:  * FIFO: singly-linked lists plus tail pointer
                     51:  * ===========================================
                     52:  *
                     53:  * This is the same as FreeBSD's sys/queue.h STAILQ -- a singly-linked
                     54:  * list implementation with tail-pointer maintenance, so that adding
                     55:  * at the tail for first-in, first-out access is O(1).
                     56:  *
                     57:  * DECL_FIFO_ANCHOR(entrytype)
                     58:  *     provides the type specification portion of the declaration for
                     59:  *     a variable to refer to a FIFO queue (similar to listhead).  The
                     60:  *     anchor contains the head and indirect tail pointers.  Example:
                     61:  *
                     62:  *             #include "ntp_lists.h"
                     63:  *
                     64:  *             typedef struct myentry_tag myentry;
                     65:  *             struct myentry_tag {
                     66:  *                     myentry *next_link;
                     67:  *                     ...
                     68:  *             };
                     69:  *
                     70:  *             DECL_FIFO_ANCHOR(myentry) my_fifo;
                     71:  *
                     72:  *             void somefunc(myentry *pentry)
                     73:  *             {
                     74:  *                     LINK_FIFO(my_fifo, pentry, next_link);
                     75:  *             }
                     76:  *
                     77:  *     If DECL_FIFO_ANCHOR is used with stack or heap storage, it
                     78:  *     should be initialized to NULL pointers using a = { NULL };
                     79:  *     initializer or memset.
                     80:  *
                     81:  * HEAD_FIFO(anchor)
                     82:  * TAIL_FIFO(anchor)
                     83:  *     Pointer to first/last entry, NULL if FIFO is empty.
                     84:  *
                     85:  * LINK_FIFO(anchor, pentry, nextlink)
                     86:  *     add entry at tail.
                     87:  *
                     88:  * UNLINK_FIFO(punlinked, anchor, nextlink)
                     89:  *     unlink head entry and point punlinked to it, or set punlinked
                     90:  *     to NULL if the list is empty.
                     91:  *
                     92:  * CONCAT_FIFO(q1, q2, nextlink)
                     93:  *     empty fifoq q2 moving its nodes to q1 following q1's existing
                     94:  *     nodes.
                     95:  *
                     96:  * DLIST: doubly-linked lists
                     97:  * ==========================
                     98:  *
                     99:  * Elements on DLISTs always have non-NULL forward and back links,
                    100:  * because both link chains are circular.  The beginning/end is marked
                    101:  * by the listhead, which is the same type as elements for simplicity.
                    102:  * An empty list's listhead has both links set to its own address.
                    103:  *
                    104:  *
                    105:  */
                    106: #ifndef NTP_LISTS_H
                    107: #define NTP_LISTS_H
                    108: 
                    109: #include "ntp_types.h"         /* TRUE and FALSE */
                    110: #include "ntp_assert.h"
                    111: 
                    112: #ifdef DEBUG
                    113: # define NTP_DEBUG_LISTS_H
                    114: #endif
                    115: 
                    116: /*
                    117:  * If list debugging is not enabled, save a little time by not clearing
                    118:  * an entry's link pointer when it is unlinked, as the stale pointer
                    119:  * is harmless as long as it is ignored when the entry is not in a
                    120:  * list.
                    121:  */
                    122: #ifndef NTP_DEBUG_LISTS_H
                    123: #define MAYBE_Z_LISTS(p)       do { } while (FALSE)
                    124: #else
                    125: #define MAYBE_Z_LISTS(p)       (p) = NULL
                    126: #endif
                    127: 
                    128: #define LINK_SLIST(listhead, pentry, nextlink)                 \
                    129: do {                                                           \
                    130:        (pentry)->nextlink = (listhead);                        \
                    131:        (listhead) = (pentry);                                  \
                    132: } while (FALSE)
                    133: 
                    134: #define LINK_TAIL_SLIST(listhead, pentry, nextlink, entrytype) \
                    135: do {                                                           \
                    136:        entrytype **pptail;                                     \
                    137:                                                                \
                    138:        pptail = &(listhead);                                   \
                    139:        while (*pptail != NULL)                                 \
                    140:                pptail = &((*pptail)->nextlink);                \
                    141:                                                                \
                    142:        (pentry)->nextlink = NULL;                              \
                    143:        *pptail = (pentry);                                     \
                    144: } while (FALSE)
                    145: 
                    146: #define LINK_SORT_SLIST_CURRENT()      (*ppentry)
                    147: #define        L_S_S_CUR()                     LINK_SORT_SLIST_CURRENT()
                    148: 
                    149: #define LINK_SORT_SLIST(listhead, pentry, beforecur, nextlink, \
                    150:                        entrytype)                              \
                    151: do {                                                           \
                    152:        entrytype **ppentry;                                    \
                    153:                                                                \
                    154:        ppentry = &(listhead);                                  \
                    155:        while (TRUE) {                                          \
                    156:                if (NULL == *ppentry || (beforecur)) {          \
                    157:                        (pentry)->nextlink = *ppentry;          \
                    158:                        *ppentry = (pentry);                    \
                    159:                        break;                                  \
                    160:                }                                               \
                    161:                ppentry = &((*ppentry)->nextlink);              \
                    162:                if (NULL == *ppentry) {                         \
                    163:                        (pentry)->nextlink = NULL;              \
                    164:                        *ppentry = (pentry);                    \
                    165:                        break;                                  \
                    166:                }                                               \
                    167:        }                                                       \
                    168: } while (FALSE)
                    169: 
                    170: #define UNLINK_HEAD_SLIST(punlinked, listhead, nextlink)       \
                    171: do {                                                           \
                    172:        (punlinked) = (listhead);                               \
                    173:        if (NULL != (punlinked)) {                              \
                    174:                (listhead) = (punlinked)->nextlink;             \
                    175:                MAYBE_Z_LISTS((punlinked)->nextlink);           \
                    176:        }                                                       \
                    177: } while (FALSE)
                    178: 
                    179: #define UNLINK_EXPR_SLIST_CURRENT()    (*ppentry)
                    180: #define        U_E_S_CUR()                     UNLINK_EXPR_SLIST_CURRENT()
                    181: 
                    182: #define UNLINK_EXPR_SLIST(punlinked, listhead, expr, nextlink, \
                    183:                          entrytype)                            \
                    184: do {                                                           \
                    185:        entrytype **ppentry;                                    \
                    186:                                                                \
                    187:        ppentry = &(listhead);                                  \
                    188:                                                                \
                    189:        while (!(expr))                                         \
                    190:                if (*ppentry != NULL &&                         \
                    191:                    (*ppentry)->nextlink != NULL) {             \
                    192:                        ppentry = &((*ppentry)->nextlink);      \
                    193:                } else {                                        \
                    194:                        ppentry = NULL;                         \
                    195:                        break;                                  \
                    196:                }                                               \
                    197:                                                                \
                    198:        if (ppentry != NULL) {                                  \
                    199:                (punlinked) = *ppentry;                         \
                    200:                *ppentry = (punlinked)->nextlink;               \
                    201:                MAYBE_Z_LISTS((punlinked)->nextlink);           \
                    202:        } else {                                                \
                    203:                (punlinked) = NULL;                             \
                    204:        }                                                       \
                    205: } while (FALSE)
                    206: 
                    207: #define UNLINK_SLIST(punlinked, listhead, ptounlink, nextlink, \
                    208:                     entrytype)                                 \
                    209:        UNLINK_EXPR_SLIST(punlinked, listhead, (ptounlink) ==   \
                    210:            U_E_S_CUR(), nextlink, entrytype)
                    211: 
                    212: #define CHECK_SLIST(listhead, nextlink, entrytype)             \
                    213: do {                                                           \
                    214:        entrytype *pentry;                                      \
                    215:                                                                \
                    216:        for (pentry = (listhead);                               \
                    217:             pentry != NULL;                                    \
                    218:             pentry = pentry->nextlink){                        \
                    219:                NTP_INSIST(pentry != pentry->nextlink);         \
                    220:                NTP_INSIST((listhead) != pentry->nextlink);     \
                    221:        }                                                       \
                    222: } while (FALSE)
                    223: 
                    224: /*
                    225:  * FIFO
                    226:  */
                    227: 
                    228: #define DECL_FIFO_ANCHOR(entrytype)                            \
                    229: struct {                                                       \
                    230:        entrytype *     phead;  /* NULL if list empty */        \
                    231:        entrytype **    pptail; /* NULL if list empty */        \
                    232: }
                    233: 
                    234: #define HEAD_FIFO(anchor)      ((anchor).phead)
                    235: #define TAIL_FIFO(anchor)      ((NULL == (anchor).pptail)      \
                    236:                                        ? NULL                  \
                    237:                                        : *((anchor).pptail))
                    238: 
                    239: /*
                    240:  * For DEBUG builds only, verify both or neither of the anchor pointers
                    241:  * are NULL with each operation.
                    242:  */
                    243: #if !defined(NTP_DEBUG_LISTS_H)
                    244: #define        CHECK_FIFO_CONSISTENCY(anchor)  do { } while (FALSE)
                    245: #else
                    246: #define        CHECK_FIFO_CONSISTENCY(anchor)                          \
                    247:        check_gen_fifo_consistency(&(anchor))
                    248: void   check_gen_fifo_consistency(void *fifo);
                    249: #endif
                    250: 
                    251: /*
                    252:  * generic FIFO element used to access any FIFO where each element
                    253:  * begins with the link pointer
                    254:  */
                    255: typedef struct gen_node_tag gen_node;
                    256: struct gen_node_tag {
                    257:        gen_node *      link;
                    258: };
                    259: 
                    260: /* generic FIFO */
                    261: typedef DECL_FIFO_ANCHOR(gen_node) gen_fifo;
                    262: 
                    263: 
                    264: #define LINK_FIFO(anchor, pentry, nextlink)                    \
                    265: do {                                                           \
                    266:        CHECK_FIFO_CONSISTENCY(anchor);                         \
                    267:                                                                \
                    268:        (pentry)->nextlink = NULL;                              \
                    269:        if (NULL != (anchor).pptail) {                          \
                    270:                (*((anchor).pptail))->nextlink = (pentry);      \
                    271:                (anchor).pptail =                               \
                    272:                    &(*((anchor).pptail))->nextlink;            \
                    273:        } else {                                                \
                    274:                (anchor).phead = (pentry);                      \
                    275:                (anchor).pptail = &(anchor).phead;              \
                    276:        }                                                       \
                    277:                                                                \
                    278:        CHECK_FIFO_CONSISTENCY(anchor);                         \
                    279: } while (FALSE)
                    280: 
                    281: #define UNLINK_FIFO(punlinked, anchor, nextlink)               \
                    282: do {                                                           \
                    283:        CHECK_FIFO_CONSISTENCY(anchor);                         \
                    284:                                                                \
                    285:        (punlinked) = (anchor).phead;                           \
                    286:        if (NULL != (punlinked)) {                              \
                    287:                (anchor).phead = (punlinked)->nextlink;         \
                    288:                if (NULL == (anchor).phead)                     \
                    289:                        (anchor).pptail = NULL;                 \
                    290:                else if ((anchor).pptail ==                     \
                    291:                         &(punlinked)->nextlink)                \
                    292:                        (anchor).pptail = &(anchor).phead;      \
                    293:                MAYBE_Z_LISTS((punlinked)->nextlink);           \
                    294:                CHECK_FIFO_CONSISTENCY(anchor);                 \
                    295:        }                                                       \
                    296: } while (FALSE)
                    297: 
                    298: #define UNLINK_MID_FIFO(punlinked, anchor, tounlink, nextlink, \
                    299:                        entrytype)                              \
                    300: do {                                                           \
                    301:        entrytype **ppentry;                                    \
                    302:                                                                \
                    303:        CHECK_FIFO_CONSISTENCY(anchor);                         \
                    304:                                                                \
                    305:        ppentry = &(anchor).phead;                              \
                    306:                                                                \
                    307:        while ((tounlink) != *ppentry)                          \
                    308:                if ((*ppentry)->nextlink != NULL) {             \
                    309:                        ppentry = &((*ppentry)->nextlink);      \
                    310:                } else {                                        \
                    311:                        ppentry = NULL;                         \
                    312:                        break;                                  \
                    313:                }                                               \
                    314:                                                                \
                    315:        if (ppentry != NULL) {                                  \
                    316:                (punlinked) = *ppentry;                         \
                    317:                *ppentry = (punlinked)->nextlink;               \
                    318:                if (NULL == *ppentry)                           \
                    319:                        (anchor).pptail = NULL;                 \
                    320:                else if ((anchor).pptail ==                     \
                    321:                         &(punlinked)->nextlink)                \
                    322:                        (anchor).pptail = &(anchor).phead;      \
                    323:                MAYBE_Z_LISTS((punlinked)->nextlink);           \
                    324:                CHECK_FIFO_CONSISTENCY(anchor);                 \
                    325:        } else {                                                \
                    326:                (punlinked) = NULL;                             \
                    327:        }                                                       \
                    328: } while (FALSE)
                    329: 
                    330: #define CONCAT_FIFO(f1, f2, nextlink)                          \
                    331: do {                                                           \
                    332:        CHECK_FIFO_CONSISTENCY(f1);                             \
                    333:        CHECK_FIFO_CONSISTENCY(f2);                             \
                    334:                                                                \
                    335:        if ((f2).pptail != NULL) {                              \
                    336:                if ((f1).pptail != NULL) {                      \
                    337:                        (*(f1).pptail)->nextlink = (f2).phead;  \
                    338:                        if ((f2).pptail == &(f2).phead)         \
                    339:                                (f1).pptail =                   \
                    340:                                    &(*(f1).pptail)->nextlink;  \
                    341:                        else                                    \
                    342:                                (f1).pptail = (f2).pptail;      \
                    343:                        CHECK_FIFO_CONSISTENCY(f1);             \
                    344:                } else  {                                       \
                    345:                        (f1) = (f2);                            \
                    346:                }                                               \
                    347:                MAYBE_Z_LISTS((f2).phead);                      \
                    348:                MAYBE_Z_LISTS((f2).pptail);                     \
                    349:        }                                                       \
                    350: } while (FALSE)
                    351: 
                    352: /*
                    353:  * DLIST
                    354:  */
                    355: #define DECL_DLIST_LINK(entrytype, link)                       \
                    356: struct {                                                       \
                    357:        entrytype *     b;                                      \
                    358:        entrytype *     f;                                      \
                    359: } link
                    360: 
                    361: #define INIT_DLIST(listhead, link)                             \
                    362: do {                                                           \
                    363:        (listhead).link.f = &(listhead);                        \
                    364:        (listhead).link.b = &(listhead);                        \
                    365: } while (FALSE)
                    366: 
                    367: #define HEAD_DLIST(listhead, link)                             \
                    368:        (                                                       \
                    369:                (&(listhead) != (listhead).link.f)              \
                    370:                    ? (listhead).link.f                         \
                    371:                    : NULL                                      \
                    372:        )
                    373: 
                    374: #define TAIL_DLIST(listhead, link)                             \
                    375:        (                                                       \
                    376:                (&(listhead) != (listhead).link.b)              \
                    377:                    ? (listhead).link.b                         \
                    378:                    : NULL                                      \
                    379:        )
                    380: 
                    381: #define NEXT_DLIST(listhead, entry, link)                      \
                    382:        (                                                       \
                    383:                (&(listhead) != (entry)->link.f)                \
                    384:                    ? (entry)->link.f                           \
                    385:                    : NULL                                      \
                    386:        )
                    387: 
                    388: #define PREV_DLIST(listhead, entry, link)                      \
                    389:        (                                                       \
                    390:                (&(listhead) != (entry)->link.b)                \
                    391:                    ? (entry)->link.b                           \
                    392:                    : NULL                                      \
                    393:        )
                    394: 
                    395: #define LINK_DLIST(listhead, pentry, link)                     \
                    396: do {                                                           \
                    397:        (pentry)->link.f = (listhead).link.f;                   \
                    398:        (pentry)->link.b = &(listhead);                         \
                    399:        (listhead).link.f->link.b = (pentry);                   \
                    400:        (listhead).link.f = (pentry);                           \
                    401: } while (FALSE)
                    402: 
                    403: #define LINK_TAIL_DLIST(listhead, pentry, link)                        \
                    404: do {                                                           \
                    405:        (pentry)->link.b = (listhead).link.b;                   \
                    406:        (pentry)->link.f = &(listhead);                         \
                    407:        (listhead).link.b->link.f = (pentry);                   \
                    408:        (listhead).link.b = (pentry);                           \
                    409: } while (FALSE)
                    410: 
                    411: #define UNLINK_DLIST(ptounlink, link)                          \
                    412: do {                                                           \
                    413:        (ptounlink)->link.b->link.f = (ptounlink)->link.f;      \
                    414:        (ptounlink)->link.f->link.b = (ptounlink)->link.b;      \
                    415:        MAYBE_Z_LISTS((ptounlink)->link.b);                     \
                    416:        MAYBE_Z_LISTS((ptounlink)->link.f);                     \
                    417: } while (FALSE)
                    418: 
                    419: #define ITER_DLIST_BEGIN(listhead, iter, link, entrytype)      \
                    420: {                                                              \
                    421:        entrytype *i_dl_nextiter;                               \
                    422:                                                                \
                    423:        for ((iter) = (listhead).link.f;                        \
                    424:             (iter) != &(listhead)                              \
                    425:             && ((i_dl_nextiter = (iter)->link.f), TRUE);       \
                    426:             (iter) = i_dl_nextiter) {
                    427: #define ITER_DLIST_END()                                       \
                    428:        }                                                       \
                    429: }
                    430: 
                    431: #define REV_ITER_DLIST_BEGIN(listhead, iter, link, entrytype)  \
                    432: {                                                              \
                    433:        entrytype *i_dl_nextiter;                               \
                    434:                                                                \
                    435:        for ((iter) = (listhead).link.b;                        \
                    436:             (iter) != &(listhead)                              \
                    437:             && ((i_dl_nextiter = (iter)->link.b), TRUE);       \
                    438:             (iter) = i_dl_nextiter) {
                    439: #define REV_ITER_DLIST_END()                                   \
                    440:        }                                                       \
                    441: }
                    442: 
                    443: #endif /* NTP_LISTS_H */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>