#ifndef UC_TAILQ_H_ #define UC_TAILQ_H_ #ifdef __GNUC__ //#define UC_INLINE __attribute__((always_inline,flatten)) #define UC_INLINE inline #else #define UC_INLINE inline #endif /** * Doubly Linked List. * It is used either as * 1) a linked list "head" - a node serving to hold pointer to the * first and last node in a list * 2) a linked list entry - a node in the linked list * * This is variant of sys/queue.h TAILQ which avoids too many conditionals. * The struct TailQ serves both as an entry/node in a linked list, * and as head of a linked list. * * Note that unlike the sys/queue.h TAILQ, the list does * not begin/end with a NULL pointer. For a entry node, the beginning/end * is a back pointer to the head node. * Traditional linked list TailQ * node->prev == NULL node->prev == head * node->next == NULL node->next == head * * Do not ever add an entry that's a NULL pointer. * */ struct TailQ { //pointer to next element, or for a head node, //pointer to the first entry struct TailQ *next; //pointer to previous element, or for a head node, //pointer to the last node struct TailQ *prev; }; #define UC_TAILQ_HEAD_INIT(name) {&(name), &(name)} #define UC_TAILQ_HEAD(name)\ struct TailQ name = UC_TAILQ_HEAD_INIT(name) static UC_INLINE void uc_tailq_init(struct TailQ *head) { head->prev = head; head->next = head; } /** Test if the tailq is empty */ static UC_INLINE int uc_tailq_empty(const struct TailQ *head) { return head->next == head->prev; } /** Insert the entry between prev and next */ static UC_INLINE void uc_tailq_insert(struct TailQ *entry, struct TailQ *prev, struct TailQ *next) { entry->prev = prev; prev->next = entry; entry->next = next; next->prev = entry; } /** Insert entry to the tail(end) of the list */ static UC_INLINE void uc_tailq_insert_tail(struct TailQ *head, struct TailQ *entry) { //head becomes entry->next, signalling the end of the list uc_tailq_insert(entry, head->prev, head); } /** Insert entry to the head(start) of the list */ static UC_INLINE void uc_tailq_insert_head(struct TailQ *head, struct TailQ *entry) { //head becomes entry->prev, signalling the end of the list uc_tailq_insert(entry, head, head->next); } /** Remove the entry from the list it is part of. * (It *must* already be part of a list. */ static UC_INLINE void uc_tailq_remove(struct TailQ *entry) { entry->prev->next = entry->next; entry->next->prev = entry->prev; //help catch illegal use: entry->next = (void*)0x101; entry->prev = (void*)0x102; } /** Iterate over a tailq. The list cannot be altered while iterating. * * @param entry a struct TailQ* to which each element is assigned. * @param head the struct TailQ* head of the tailq */ #define UC_TAILQ_FOREACH(entry, head)\ for ((entry) = (head)->next; (entry) != (head); (entry) = (entry)->next) /** Iterate over a tailq in reverse order. The list cannot be altered while * iterating. * * @param entry a struct TailQ* to which each element is assigned. * @param head the struct TailQ* head of the tailq */ #define UC_TAILQ_FOREACH_REVERSE(entry, head)\ for ((entry) = (head)->prev; (entry) != (head); (entry) = (entry)->prev) /** Iterate over a tailq. safe to remove the entry when iterating. * * @param entry a struct TailQ* to which each element is assigned. * @param nxt a struct TailQ* needed for temporary storage. * @param head the struct TailQ* head of the tailq */ #define UC_TAILQ_FOREACH_SAFE(entry, nxt, head)\ for ((entry) = (head)->next, nxt = (entry)->next; \ (entry) != (head); \ (entry) = (nxt), (nxt) = (entry)->next) /** Iterate over a tailq in reverse order. safe to remove the entry when * iterating. * * @param entry a struct TailQ* to which each element is assigned. * @param prv a struct TailQ* needed for temporary storage. * @param head the struct TailQ* head of the tailq */ #define UC_TAILQ_FOREACH_REVERSE_SAFE(entry, prv, head)\ for ((entry) = (head)->prev, prev = (entry)->prev; \ (entry) != (head); \ (entry) = (prv), (prv) = (entry)->prev) #endif