/** * @file list.h * @brief Linux 内核风格侵入式双向循环链表(纯头文件,C/C++ 兼容) * @details 将 struct list_head 嵌入宿主结构体,通过 list_entry 取回宿主指针。 * 所有操作 O(1),遍历 O(n)。 * C++ 兼容:变量名不使用 new/class/typeof 等关键字。 */ #ifndef _LIST_H_ #define _LIST_H_ #include #ifdef __cplusplus extern "C" { #endif /* ---- 链表节点 ---- */ struct list_head { struct list_head *next; struct list_head *prev; }; /* ---- 初始化 ---- */ #define LIST_HEAD_INIT(n) { &(n), &(n) } #define LIST_HEAD(n) struct list_head n = LIST_HEAD_INIT(n) /** * @brief 运行时初始化链表头 */ static inline void INIT_LIST_HEAD(struct list_head *h) { h->next = h; h->prev = h; } /* ---- 内部辅助:在 prev 和 next 之间插入 node ---- */ static inline void __list_add(struct list_head *node, struct list_head *prev, struct list_head *next) { next->prev = node; node->next = next; node->prev = prev; prev->next = node; } /* ---- 内部辅助:移除 prev 和 next 之间的节点 ---- */ static inline void __list_del(struct list_head *prev, struct list_head *next) { next->prev = prev; prev->next = next; } /* ---- 添加操作 ---- */ /** 头插法:插入到 head 之后(作为第一个元素) */ static inline void list_add(struct list_head *node, struct list_head *head) { __list_add(node, head, head->next); } /** 尾插法:插入到 head 之前(作为最后一个元素) */ static inline void list_add_tail(struct list_head *node, struct list_head *head) { __list_add(node, head->prev, head); } /* ---- 删除操作 ---- */ /** 从链表移除节点(不释放内存) */ static inline void list_del(struct list_head *e) { __list_del(e->prev, e->next); } /** 移除并重新初始化节点(安全删除,防止悬空指针) */ static inline void list_del_init(struct list_head *e) { __list_del(e->prev, e->next); INIT_LIST_HEAD(e); } /* ---- 移动操作 ---- */ /** 将节点移动到新链表头部 */ static inline void list_move(struct list_head *l, struct list_head *h) { __list_del(l->prev, l->next); list_add(l, h); } /** 将节点移动到新链表尾部 */ static inline void list_move_tail(struct list_head *l, struct list_head *h) { __list_del(l->prev, l->next); list_add_tail(l, h); } /* ---- 替换操作 ---- */ /** 用 node 替换 old */ static inline void list_replace(struct list_head *old, struct list_head *node) { node->next = old->next; node->next->prev = node; node->prev = old->prev; node->prev->next = node; } /** 替换后初始化被替换节点 */ static inline void list_replace_init(struct list_head *old, struct list_head *node) { list_replace(old, node); INIT_LIST_HEAD(old); } /* ---- 判断操作 ---- */ /** 判断链表是否为空 */ static inline int list_empty(const struct list_head *h) { return h->next == h; } /** 判断节点是否已链入链表 */ static inline int list_is_linked(const struct list_head *e) { return e->next != e; } /* ---- 节点 ↔ 宿主指针转换 ---- */ /** 从链表节点指针取回宿主结构体指针 */ #define list_entry(ptr, type, member) \ ((type *)((char *)(ptr) - offsetof(type, member))) /** 获取第一个宿主元素 */ #define list_first_entry(h, type, member) \ list_entry((h)->next, type, member) /** 获取最后一个宿主元素 */ #define list_last_entry(h, type, member) \ list_entry((h)->prev, type, member) /** 安全获取第一个元素(链表空返回 NULL) */ #define list_first_entry_or_null(h, type, member) \ (list_empty(h) ? NULL : list_first_entry(h, type, member)) /* ---- 遍历操作 ---- */ /** 遍历链表节点(仅获取 struct list_head 指针) */ #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) /** 安全遍历节点(可在遍历中删除 pos) */ #define list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next) /** 遍历宿主元素 */ #define list_for_each_entry(pos, head, member) \ for (pos = list_first_entry(head, __typeof__(*pos), member); \ &pos->member != (head); \ pos = list_entry(pos->member.next, __typeof__(*pos), member)) /** 安全遍历宿主元素(可在遍历中删除 pos) */ #define list_for_each_entry_safe(pos, n, head, member) \ for (pos = list_first_entry(head, __typeof__(*pos), member), \ n = list_entry(pos->member.next, __typeof__(*pos), member); \ &pos->member != (head); \ pos = n, \ n = list_entry(n->member.next, __typeof__(*n), member)) /* ---- 拼接操作 ---- */ /** 将 src 链表拼接到 dst 头部,src 被清空 */ static inline void list_splice_init(struct list_head *src, struct list_head *dst) { if (!list_empty(src)) { struct list_head *f = src->next; struct list_head *l = src->prev; struct list_head *a = dst->next; f->prev = dst; dst->next = f; l->next = a; a->prev = l; INIT_LIST_HEAD(src); } } #ifdef __cplusplus } #endif #endif /* _LIST_H_ */