/* Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef QUEUE_H_
#define QUEUE_H_
#include <stddef.h>
/*
* 使用指针数组QUEUE记录队列的头和尾
*/
typedef void *QUEUE[2];
/* Private macros. */
// 获取队列节点 `q` 的后继节点。
#define QUEUE_NEXT(q) (*(QUEUE **) &((*(q))[0]))
// 获取队列节点 `q` 的前驱节点。
#define QUEUE_PREV(q) (*(QUEUE **) &((*(q))[1]))
/*
* 为什么不直接返回 q?
* 代码一致性: 为了保持代码风格和逻辑的一致性,使用宏定义 QUEUE_PREV_NEXT(q) 更加清晰,也更容易理解。
* 潜在的异常情况: 虽然在正常情况下,QUEUE_PREV_NEXT(q) 会返回 q 本身,但在某些特殊情况下,例如队列
* 被坏或者节点被移除,QUEUE_PREV_NEXT(q) 的结果可能不再是 q。使用宏定义可以更好地处理这些异常情况。
*
* 例如:
* QUEUE *q = QUEUE_HEAD(queue); // 获取队列头节点 QUEUE_REMOVE(q); // 将 q 从队列中移除
* 此时,q 的前驱节点的后继节点已经不再是 q 了。如果直接返回 q,就会得到一个无效的节点。而
* 使用 QUEUE_PREV_NEXT(q),可以正确地获取到 q 被移除后,它的前驱节点的新后继节点。
*/
// 获取队列节点 q 的前驱节点的后继节点(通常情况下,这会返回 q 本身)。
#define QUEUE_PREV_NEXT(q) (QUEUE_NEXT(QUEUE_PREV(q)))
// 获取队列节点 q 的后继节点的前驱节点(通常情况下,这会返回 q 本身)。
#define QUEUE_NEXT_PREV(q) (QUEUE_PREV(QUEUE_NEXT(q)))
/* Public macros. */
/*
* 从队列节点指针 ptr 中提取用户数据。该宏假设用户数据是嵌入在更大的结构体 type 中的,并且 field 是
* 指向队列节点指针的成员变量。通过减去 `field` 成员的偏移量,可以得到包含用户数据的结构体的起始地址。
*/
#define QUEUE_DATA(ptr, type, field) \
((type *) ((char *) (ptr) - offsetof(type, field)))
/* Important note: mutating the list while QUEUE_FOREACH is
* iterating over its elements results in undefined behavior.
* 这是一个用于遍历队列的宏。h 是队列的头节点,q 是遍历过程中的当前节点。循环从 h 的后继节点开始,
* 直到回到 h 时结束。
*/
#define QUEUE_FOREACH(q, h) \
for ((q) = QUEUE_NEXT(h); (q) != (h); (q) = QUEUE_NEXT(q))
//判断队列 q 是否为空。如果 q 的后继节点是它自己,则队列为空。
#define QUEUE_EMPTY(q) \
((const QUEUE *) (q) == (const QUEUE *) QUEUE_NEXT(q))
// 获取队列 q 的头节点(第一个元素)。
#define QUEUE_HEAD(q) \
(QUEUE_NEXT(q))
// 初始化队列 q。将 q 的前驱和后继都指向自己,表示这是一个空队列。
#define QUEUE_INIT(q) \
do { \
QUEUE_NEXT(q) = (q); \
QUEUE_PREV(q) = (q); \
} \
while (0)
// 在队列 h 的末尾添加节点 n。
#define QUEUE_ADD(h, n) \
do { \
QUEUE_PREV_NEXT(h) = QUEUE_NEXT(n); \
QUEUE_NEXT_PREV(n) = QUEUE_PREV(h); \
QUEUE_PREV(h) = QUEUE_PREV(n); \
QUEUE_PREV_NEXT(h) = (h); \
} \
while (0)
// 将队列 h 在节点 q 处拆分为两个队列,前一部分仍然是 h,后一部分是新的队列 n。
#define QUEUE_SPLIT(h, q, n) \
do { \
QUEUE_PREV(n) = QUEUE_PREV(h); \
QUEUE_PREV_NEXT(n) = (n); \
QUEUE_NEXT(n) = (q); \
QUEUE_PREV(h) = QUEUE_PREV(q); \
QUEUE_PREV_NEXT(h) = (h); \
QUEUE_PREV(q) = (n); \
} \
while (0)
// 将队列 h 中的所有节点移动到队列 n 中。
#define QUEUE_MOVE(h, n) \
do { \
if (QUEUE_EMPTY(h)) \
QUEUE_INIT(n); \
else { \
QUEUE* q = QUEUE_HEAD(h); \
QUEUE_SPLIT(h, q, n); \
} \
} \
while (0)
// 在队列 h 的头部插入节点 q。
#define QUEUE_INSERT_HEAD(h, q) \
do { \
QUEUE_NEXT(q) = QUEUE_NEXT(h); \
QUEUE_PREV(q) = (h); \
QUEUE_NEXT_PREV(q) = (q); \
QUEUE_NEXT(h) = (q); \
} \
while (0)
// 在队列 h 的末尾插入节点 q。
#define QUEUE_INSERT_TAIL(h, q) \
do { \
QUEUE_NEXT(q) = (h); \
QUEUE_PREV(q) = QUEUE_PREV(h); \
QUEUE_PREV_NEXT(q) = (q); \
QUEUE_PREV(h) = (q); \
} \
while (0)
// 将节点 q 从所在的队列中移除。
#define QUEUE_REMOVE(q) \
do { \
QUEUE_PREV_NEXT(q) = QUEUE_NEXT(q); \
QUEUE_NEXT_PREV(q) = QUEUE_PREV(q); \
} \
while (0)
#endif /* QUEUE_H_ */