QList链表不是内核里的双向链表那样直观,记录原理:
typedef struct QTailQLink {
void *tql_next;
struct QTailQLink *tql_prev;
} QTailQLink;
/*
* Tail queue definitions. The union acts as a poor man template, as if
* it were QTailQLink<type>.
*/
#define QTAILQ_HEAD(name, type) \
union name { \
struct type *tqh_first; /* first element */ \
QTailQLink tqh_circ; /* link for circular backwards list */ \
}
#define QTAILQ_HEAD_INITIALIZER(head) \
{ .tqh_circ = { NULL, &(head).tqh_circ } }
#define QTAILQ_ENTRY(type) \
union { \
struct type *tqe_next; /* next element */ \
QTailQLink tqe_circ; /* link for circular backwards list */ \
}
不清楚为啥要这么管理,这竟然是一个union。如果作为head指针,则使用QTAIL里的一个指针tqh_first字段,用来记录第一个数据。如果作为有效数据,则包含两个指针,tql_next用来指向下一个数据(void *),tql_prev用来指向上一个QTAIL里的QTailQLink字段(struct QTailQLink*)。
相应的QTAIL接口都是用宏定义命名的,有多组不同的接口。
QTAILQ_INSERT_HEAD,插入到头部;
QTAIL_INSERT_TAIL, 插入到尾部;
QTAIL_INSERT_AFTER, 插入某元素后面;
QTAIL_INSERT_BEFORE,插入某元素前面。
单纯的不能理解到这种实现方式的意义。
目的是可以通过next指针直接寻址到外层数据结构?这样可以将不同数据结构链接到一个链表里???
那么,这个链表是通过tql_prev这个指针串联起来的,next指针并不可以遍历整个链表。但看起来实际并不是这样实现的。因为正向遍历的宏定义就会按照next指针遍历。而且,将不同数据结构链接到一个链表里的意义是什么,如何区分不同的结构做不同的处理,看起来没有意义。
那或许是,避免了一次CONTAINER_OF()的操作?可以通过next指针直接获取数据结构的首地址。查看代码,即使是使用prev指针反向遍历,也是通过prev->prev->next的形式直接获取到数据结构的起始地址。