Add tailq linked list
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
#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
|
||||
Reference in New Issue
Block a user