队列
libuv源码分析——1.queue:https://blog.csdn.net/AnitaSun/article/details/123968659
//queue.h
#ifndef QUEUE_H_
#define QUEUE_H_
#include <stddef.h>
typedef void *QUEUE[2];
//保证是左值,能进行赋值操作
#define QUEUE_NEXT(q) (*(QUEUE **) &((*(q))[0]))
#define QUEUE_PREV(q) (*(QUEUE **) &((*(q))[1]))
#define QUEUE_PREV_NEXT(q) (QUEUE_NEXT(QUEUE_PREV(q)))
#define QUEUE_NEXT_PREV(q) (QUEUE_PREV(QUEUE_NEXT(q)))
//offsetof,用来获取属性field在指定类型type的位置偏差,然后通过用ptr在内存中的地址减去该偏差就能得到对象在内存中的初始位置。
#define QUEUE_DATA(ptr, type, field) \
((type *) ((char *) (ptr) - offsetof(type, field)))
//for循环不断取队列h中的元素,将其赋给q
#define QUEUE_FOREACH(q, h) \
for ((q) = QUEUE_NEXT(h); (q) != (h); (q) = QUEUE_NEXT(q))
// 队列为空判断
#define QUEUE_EMPTY(q) \
((const QUEUE *) (q) == (const QUEUE *) QUEUE_NEXT(q))
// 获取队列头
#define QUEUE_HEAD(q) \
(QUEUE_NEXT(q))
#define QUEUE_TAIL(q) \
(QUEUE_PREV(q))
// 队列初始化
// do while包裹,让其变为一个整体,反例是放到if语句中
#define QUEUE_INIT(q) \
do { \
QUEUE_NEXT(q) = (q); \
QUEUE_PREV(q) = (q); \
} \
while (0)
// 队列相加
#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为分割点进行分割,分割出来的新队列为n(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)
// 向队列头插入节点
#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)
// 向队列尾插入节点
// 将元素q加入到队列h的尾部
#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)
// 队列删除
#define QUEUE_REMOVE(q) \
do { \
QUEUE_PREV_NEXT(q) = QUEUE_NEXT(q); \
QUEUE_NEXT_PREV(q) = QUEUE_PREV(q); \
} \
while (0)
#endif /* QUEUE_H_ */
示例代码
#include <stdio.h>
#include "queue.h" // 引入队列
// 定义一个结构Work类型的struct类型
typedef struct {
int index;
QUEUE q;
} Work;
// 输出Work类型数据
void printWork(Work* work) {
printf("work->index:%i\n", work->index);
}
int main() {
// 定义队列的头节点
QUEUE start;
QUEUE_INIT(&start);
// 创建10个Work对象
int num = 10;
Work works[num];
for(int i = 0; i < num; ++i) {
// 给每个work队形的index属性赋值
works[i].index = i;
// 将每个work对象插入到队列中
QUEUE_INSERT_TAIL(&start, &works[i].q);
}
QUEUE* tmpQ;
Work* tmpWork;
// 遍历队列
QUEUE_FOREACH(tmpQ, &start){
// 根据队列指针返回work对象
tmpWork = QUEUE_DATA(tmpQ, Work, q);
// 输出队列数据
printWork(tmpWork);
}
return 0;
}