一个美丽的queue

51 阅读3分钟
/* 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_ */