一,前述
由于接触蓝牙协议栈相关工作,涉及很多mbuf,mqueue的操作,其中不乏Berkeley queue的身影,故因此,深入了解一下链表以及队列相关操作,九几年的代码放在现在依旧经典,需要深入琢磨多次!该部分包含5个部分,单向链表,双向链表,队列,尾队列,环形队列。
(注:在此之后,将依赖此深入了解mbuf与mqueue)
文件索引地址:https://github.com/torvalds/linux/blob/master/drivers/scsi/aic7xxx/queue.h
二,Singly-Linked List,SLIST
俗称:单向链表
1,声明
// 用于定义一个单向链表数据结构体的头变量,该结构体只有一个指针成员slh_first,指向第一个type类型的数据结构;
#define SLIST_HEAD(name, type) \
struct name { \
struct type *slh_first; /* first element */ \
}
// 用于在定义时初始化SLIST_HEAD定义的数据结构体的头变量;
#define SLIST_HEAD_INITIALIZER(head) \
{ NULL }
// 用于定义一个(用户)结构体的成员变量,该成员变量只包含一个指向type类型的指针sle_next;
#define SLIST_ENTRY(type) \
struct { \
struct type *sle_next; /* next element */ \
}
2,函数
// 用于判断单向链表是否为空:空则返回true,否则返回false;
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
// 用于获取单向链表的第一个元素;
#define SLIST_FIRST(head) ((head)->slh_first)
// 用于遍历单向链表,var是临时变量,head是链表头指针(SLIST_HEAD定义的变量),field是SLIST_ENTRY定义的成员变量名;
#define SLIST_FOREACH(var, head, field) \
for ((var) = SLIST_FIRST((head)); \
(var); \
(var) = SLIST_NEXT((var), field))
// 用于初始化SLIST_HEAD定义的头指针变量;
#define SLIST_INIT(head) do { \
SLIST_FIRST((head)) = NULL; \
} while (0)
// 用于将元素elm插入到当前链表元素slistelm的后面;
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
SLIST_NEXT((slistelm), field) = (elm); \
} while (0)
// 用于将元素elm插入到当前链表head的头部;head是SLIST_HEAD定义的链表头指针;
#define SLIST_INSERT_HEAD(head, elm, field) do { \
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
SLIST_FIRST((head)) = (elm); \
} while (0)
// 用于获取elm元素的下一个元素,field是前面用SLIST_ENTRY定义的成员变量名;
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
// 用于从head链表中删除elm元素;注意首先判断elm元素是否在head链表中,否则会崩溃;
#define SLIST_REMOVE(head, elm, type, field) do { \
if (SLIST_FIRST((head)) == (elm)) { \
SLIST_REMOVE_HEAD((head), field); \
} \
else { \
struct type *curelm = SLIST_FIRST((head)); \
while (SLIST_NEXT(curelm, field) != (elm)) \
curelm = SLIST_NEXT(curelm, field); \
SLIST_NEXT(curelm, field) = \
SLIST_NEXT(SLIST_NEXT(curelm, field), field); \
} \
} while (0)
// 用于删除第一个元素;注意删除时判断head是否为空,否则会崩溃;
#define SLIST_REMOVE_HEAD(head, field) do { \
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
} while (0)
3,模型
4,验证例程
#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>
struct SLIST_ITEM {
int value;
SLIST_ENTRY(SLIST_ITEM) entry;
};
static SLIST_HEAD(,SLIST_ITEM) slist_head;
int main(int argc, char *argv[])
{
int i = 0;
struct SLIST_ITEM *item;
struct SLIST_ITEM *tmp_item;
SLIST_INIT(&slist_head);
if (SLIST_EMPTY(&slist_head)) {
printf("single list is empty\n");
}
for( i = 0; i < 10; i ++) {
item = (struct SLIST_ITEM *)malloc(sizeof(struct SLIST_ITEM));
item->value = i;
// 头部插入:即9,8,7,6,5,4,3,2,1,0
// 用于将元素item插入到当前链表slist_head的头部
SLIST_INSERT_HEAD(&slist_head, item, entry);
}
for( i = 0; i < 10; i ++) {
tmp_item = (struct SLIST_ITEM *)malloc(sizeof(struct SLIST_ITEM));
tmp_item->value = i + 10;
// 尾部插入:即9,10,11,12...19,8,7,..1,0
// 用于将元素tmp_item插入到item的后面
SLIST_INSERT_AFTER(item, tmp_item, entry);
// 置换位置,让下一个元素在当前元素之后
item = tmp_item;
}
printf("after insert 10 item to single list:\n");
SLIST_FOREACH(item, &slist_head, entry)
printf("Has Item pointer = %p, item value = %d\n", item, item->value);
SLIST_FOREACH(tmp_item, &slist_head, entry) {
// 将删除1.3.5.7.9...
// 用于从slist_head链表中删除tmp_item元素
if(tmp_item->value % 2 != 0) {
printf("Remove item pointer = %p, item value = %d\n", tmp_item, tmp_item->value);
SLIST_REMOVE(&slist_head, tmp_item, SLIST_ITEM, entry);
free(tmp_item);
}
}
printf("after delete items from single list, the rest:\n");
SLIST_FOREACH(item, &slist_head, entry)
printf("Has Item pointer = %p, item value = %d\n", item, item->value);
SLIST_FOREACH(tmp_item, &slist_head, entry) {
// 删除slist_head链表中头部元素
printf("Remove head item pointer = %p, item value = %d\n", tmp_item, tmp_item->value);
SLIST_REMOVE_HEAD(&slist_head, entry);
free(tmp_item);
}
if (SLIST_EMPTY(&slist_head)) {
printf("single list is empty!!!\n");
}
return 0;
}
三,Singly-linked Tail Queue,STAILQ
俗称:单向有尾队列
1,声明
// 用于定义一个单向有尾队列数据结构体的头变量,该结构体有两个指针成员stqh_first和stqh_last,分别指向第一个type类型的数据结构,和最后一个type类型的数据结构;
#define STAILQ_HEAD(name, type) \
struct name { \
struct type *stqh_first;/* first element */ \
struct type **stqh_last;/* addr of last next element */ \
}
// 用于在定义时初始化STAILQ_HEAD定义的数据结构体的头变量;
#define STAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).stqh_first }
// 用于定义一个(用户)结构体的成员变量,该成员变量只包含一个指向type类型的指针stqe_next;
#define STAILQ_ENTRY(type) \
struct { \
struct type *stqe_next; /* next element */ \
}
2,函数
// 用于判断单向有尾队列是否为空:空则返回true,否则返回false;
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
// 用于返回单向有尾队列的第一个元素;
#define STAILQ_FIRST(head) ((head)->stqh_first)
// 用于遍历单向有尾队列,var是临时变量,head是链表头指针(STAILQ_HEAD定义的变量指针),field是STAILQ_ENTRY定义的成员变量名,headname是用户自定义的数据类型;
#define STAILQ_FOREACH(var, head, field) \
for((var) = STAILQ_FIRST((head)); \
(var); \
(var) = STAILQ_NEXT((var), field))
// 用于初始化STAILQ_HEAD定义的头指针变量;
#define STAILQ_INIT(head) do { \
STAILQ_FIRST((head)) = NULL; \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
// 用于将元素elm插入到单向有尾队列head的tqelm后面;head是STAILQ_HEAD定义的链表头指针;
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
STAILQ_NEXT((tqelm), field) = (elm); \
} while (0)
// 用于将元素elm插入到单向有尾队列head的头部;head是STAILQ_HEAD定义的链表头指针;
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
STAILQ_FIRST((head)) = (elm); \
} while (0)
// 用于将元素elm插入到单向有尾队列head的尾部;head是STAILQ_HEAD定义的链表头指针;
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
STAILQ_NEXT((elm), field) = NULL; \
*(head)->stqh_last = (elm); \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
// 用于获取单向有尾队列的最后一个元素;
#define STAILQ_LAST(head, type, field) \
(STAILQ_EMPTY(head) ? \
NULL : \
((struct type *) \
((char *)((head)->stqh_last) - offsetof(struct type, field))))
// 用于获取单向有尾队列elm的下一个元素;field是前面用STAILQ_ENTRY定义的成员变量名;
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
// 用于单向有尾队列head中删除elm元素;
#define STAILQ_REMOVE(head, elm, type, field) do { \
if (STAILQ_FIRST((head)) == (elm)) { \
STAILQ_REMOVE_HEAD(head, field); \
} \
else { \
struct type *curelm = STAILQ_FIRST((head)); \
while (STAILQ_NEXT(curelm, field) != (elm)) \
curelm = STAILQ_NEXT(curelm, field); \
if ((STAILQ_NEXT(curelm, field) = \
STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
(head)->stqh_last = &STAILQ_NEXT((curelm), field);\
} \
} while (0)
// 用于单向有尾队列head中删除头部;
#define STAILQ_REMOVE_HEAD(head, field) do { \
if ((STAILQ_FIRST((head)) = \
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
// 用于单向有尾队列head中删除从头部至elm元素;
#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
// 用于单向有尾队列head中删除elm之后的元素;
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
if ((STAILQ_NEXT(elm, field) = \
STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
3,模型
4,验证例程
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>
struct entry {
int value;
STAILQ_ENTRY(entry) entries; /* Singly linked tail queue */
};
static STAILQ_HEAD(stailhead, entry) stailq_head;
int
main(void)
{
struct entry *item1, *item2, *item3, *item_temp;
STAILQ_INIT(&stailq_head); /* Initialize the queue */
if(STAILQ_EMPTY(&stailq_head)) {
printf("stailq_head is NULL\n");
}
item1 = malloc(sizeof(struct entry));
item1->value = 1;
STAILQ_INSERT_HEAD(&stailq_head, item1, entries); /* Insert at the stailq_head */
item1 = malloc(sizeof(struct entry));
item1->value = 2;
STAILQ_INSERT_TAIL(&stailq_head, item1, entries); /* Insert at the tail */
item2 = malloc(sizeof(struct entry));
item2->value = 3;
STAILQ_INSERT_AFTER(&stailq_head, item1, item2, entries); /* Insert after */
STAILQ_FOREACH(item_temp, &stailq_head, entries)
printf("Has Item pointer = %p, item value = %d\n", item_temp, item_temp->value);
STAILQ_REMOVE(&stailq_head, item2, entry, entries); /* Deletion */
free(item2);
item3 = STAILQ_FIRST(&stailq_head);
STAILQ_REMOVE_HEAD(&stailq_head, entries); /* Deletion from the stailq_head */
free(item3);
printf("After do STAILQ_INSERT_HEAD\n");
item1 = STAILQ_FIRST(&stailq_head);
item1->value = 0;
for (int i = 1; i < 10; i++) {
item1 = malloc(sizeof(struct entry));
item1->value = i;
// 头插:9,8, ... 4, 3, 2, 1, 0
STAILQ_INSERT_HEAD(&stailq_head, item1, entries);
}
STAILQ_FOREACH(item_temp, &stailq_head, entries)
printf("Has Item pointer = %p, item value = %d\n", item_temp, item_temp->value);
printf("After do STAILQ_INSERT_TAIL\n");
for (int i = 1; i < 10; i++) {
item1 = malloc(sizeof(struct entry));
item1->value = i + 10;
// 头插:9,8, ... 4, 3, 2, 1, 0
STAILQ_INSERT_TAIL(&stailq_head, item1, entries);
}
STAILQ_FOREACH(item_temp, &stailq_head, entries)
printf("Has Item pointer = %p, item value = %d\n", item_temp, item_temp->value);
printf("After do STAILQ_INSERT_AFTER\n");
item_temp = item1;
for (int i = 1; i < 10; i++) {
item1 = malloc(sizeof(struct entry));
item1->value = i + 20;
// 头插:9,8, ... 4, 3, 2, 1, 0
STAILQ_INSERT_AFTER(&stailq_head, item_temp, item1, entries);
item_temp = item1;
}
STAILQ_FOREACH(item_temp, &stailq_head, entries)
printf("Has Item pointer = %p, item value = %d\n", item_temp, item_temp->value);
// printf("After do STAILQ_REMOVE_HEAD_UNTIL\n");
// item_temp = STAILQ_FIRST(&stailq_head);
// while (item_temp != NULL) {
// if(item_temp->value == 6) {
// // STAILQ_REMOVE_AFTER(&stailq_head, item_temp, entries);
// // STAILQ_REMOVE_HEAD(&stailq_head, entries);
// // if ((STAILQ_FIRST((&stailq_head)) = STAILQ_NEXT((item_temp), entries)) == NULL)
// // (&stailq_head)->stqh_last = &STAILQ_FIRST((&stailq_head));
// }
// item_temp = STAILQ_NEXT(item_temp, entries);
// }
// STAILQ_FOREACH(item_temp, &stailq_head, entries)
// printf("Has Item pointer = %p, item value = %d\n", item_temp, item_temp->value);
printf("After do DELETE ALL ELEMENTS\n");
// 删除所有元素
item1 = STAILQ_FIRST(&stailq_head);
while (item1 != NULL) {
item2 = STAILQ_NEXT(item1, entries);
free(item1);
item1 = item2;
}
STAILQ_INIT(&stailq_head);
if(STAILQ_EMPTY(&stailq_head)) {
printf("stailq_head is NULL\n");
}
exit(EXIT_SUCCESS);
}
四,Linked List,LIST
俗称:双向链表
1,声明
// 用于定义一个双向链表数据结构体的头变量,该结构体只有一个指针成员lh_first,指向第一个type类型的数据结构;
#define LIST_HEAD(name, type) \
struct name { \
struct type *lh_first; /* first element */ \
}
// 用于在定义时初始化LIST_HEAD定义的数据结构体的头变量;
#define LIST_HEAD_INITIALIZER(head) \
{ NULL }
// 用于定义一个(用户)结构体的成员变量,该成员变量包含两个指向type类型的指针le_next、le_prev;
#define LIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
2,函数
// 用于判断双向链表是否为空:空则返回true,否则返回false;
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
// 用于获取双向链表的第一个元素;
#define LIST_FIRST(head) ((head)->lh_first)
// 用于正向遍历双向链表,var是临时变量,head是链表头指针(LIST_HEAD定义的变量),field是LIST_ENTRY定义的成员变量名;
#define LIST_FOREACH(var, head, field) \
for ((var) = LIST_FIRST((head)); \
(var); \
(var) = LIST_NEXT((var), field))
// 用于初始化LIST_HEAD定义的头指针变量;当然也可以在使用LIST_HEAD定义头指针变量时同时使用
#define LIST_INIT(head) do { \
LIST_FIRST((head)) = NULL; \
} while (0)
// 用于将元素elm插入到当前链表元素listelm的后面;
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
LIST_NEXT((listelm), field)->field.le_prev = \
&LIST_NEXT((elm), field); \
LIST_NEXT((listelm), field) = (elm); \
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \
} while (0)
// 用于将元素elm插入到当前链表元素listelm的前面;
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.le_prev = (listelm)->field.le_prev; \
LIST_NEXT((elm), field) = (listelm); \
*(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &LIST_NEXT((elm), field); \
} while (0)
// 用于将元素elm插入到当前链表head的头部;head是LIST_HEAD定义的链表头指针;
#define LIST_INSERT_HEAD(head, elm, field) do { \
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
LIST_FIRST((head)) = (elm); \
(elm)->field.le_prev = &LIST_FIRST((head)); \
} while (0)
// 用于获取elm元素的下一个元素,field是前面用LIST_ENTRY定义的成员变量名;
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
// 用于将elm元素从链表中删除;注意首先确定elm元素确实在链表中,否则会崩溃;
#define LIST_REMOVE(elm, field) do { \
if (LIST_NEXT((elm), field) != NULL) \
LIST_NEXT((elm), field)->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
} while (0)
3,模型
4,验证例程
#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>
struct LIST_ITEM {
int value;
LIST_ENTRY(LIST_ITEM) entry;
};
static LIST_HEAD(,LIST_ITEM) slist_head;
int main(int argc, char *argv[])
{
int i = 0;
struct LIST_ITEM *item;
struct LIST_ITEM *tmp_item;
LIST_INIT(&slist_head);
if (LIST_EMPTY(&slist_head))
printf("List is empty\n");
printf("after do LIST_INSERT_HEAD:\n");
for( i = 0; i < 10; i ++) {
item = (struct LIST_ITEM *)malloc(sizeof(struct LIST_ITEM));
item->value = i;
LIST_INSERT_HEAD(&slist_head, item, entry);
}
LIST_FOREACH(tmp_item, &slist_head, entry)
printf("Has Item pointer = %p, item value = %d\n", tmp_item, tmp_item->value);
printf("after do LIST_INSERT_AFTER:\n");
for( i = 0; i < 10; i ++) {
tmp_item = (struct LIST_ITEM *)malloc(sizeof(struct LIST_ITEM));
tmp_item->value = i + 10;
// LIST_INSERT_AFTER(item, tmp_item, entry);
LIST_INSERT_BEFORE(item, tmp_item, entry);
item = tmp_item;
}
LIST_FOREACH(tmp_item, &slist_head, entry)
printf("Has Item pointer = %p, item value = %d\n", tmp_item, tmp_item->value);
printf("after do LIST_REMOVE:\n");
LIST_FOREACH(tmp_item, &slist_head, entry) {
LIST_REMOVE(tmp_item, entry);
free(tmp_item);
}
LIST_FOREACH(tmp_item, &slist_head, entry)
printf("Has Item pointer = %p, item value = %d\n", tmp_item, tmp_item->value);
if (LIST_EMPTY(&slist_head))
printf("List is empty\n");
exit(EXIT_SUCCESS);
return 0;
}
五,Tail Queue,TAILQ
俗称:尾队列
1,声明
// 用于定义一个尾队列数据结构体的头变量,该结构体有两个指针成员tqh_first和tqh_last,分别指向第一个type类型的数据结构,和最后一个type类型的数据结构;
#define TAILQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \
}
// 用于在定义时初始化TAILQ_HEAD定义的数据结构体的头变量;
#define TAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first }
// 用于定义一个(用户)结构体的成员变量,该成员变量包含两个指向type类型的指针tqe_next和tqe_prev;
#define TAILQ_ENTRY(type) \
struct { \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
}
2,函数
// 用于判定尾队列是否为空,空则返回true,非空则为false
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
// 用于获取尾队列的第一个元素;
#define TAILQ_FIRST(head) ((head)->tqh_first)
// 用于正向遍历尾队列,var是临时变量,head是链表头指针(TAILQ_HEAD定义的变量指针),field是TAILQ_ENTRY定义的成员变量名,headname是用户自定义的数据类型;
#define TAILQ_FOREACH(var, head, field) \
for ((var) = TAILQ_FIRST((head)); \
(var); \
(var) = TAILQ_NEXT((var), field))
// 用于正向遍历尾队列,var是临时变量,head是链表头指针(TAILQ_HEAD定义的变量指针),field是TAILQ_ENTRY定义的成员变量名,headname是用户自定义的数据类型;
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
for ((var) = TAILQ_LAST((head), headname); \
(var); \
(var) = TAILQ_PREV((var), headname, field))
// 用于正向遍历尾队列,var是临时变量,head是链表头指针(TAILQ_HEAD定义的变量指针),field是TAILQ_ENTRY定义的成员变量名,headname是用户自定义的数据类型;
#define TAILQ_INIT(head) do { \
TAILQ_FIRST((head)) = NULL; \
(head)->tqh_last = &TAILQ_FIRST((head)); \
} while (0)
// 用于将元素elm插入到尾队列head的listelm后面;head是TAILQ_HEAD定义的链表头指针;
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
TAILQ_NEXT((elm), field)->field.tqe_prev = \
&TAILQ_NEXT((elm), field); \
else \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
TAILQ_NEXT((listelm), field) = (elm); \
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
} while (0)
// 用于将元素elm插入到尾队列中listelm元素前面;
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
TAILQ_NEXT((elm), field) = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
} while (0)
// 用于将元素elm插入到尾队列head的头部;head是TAILQ_HEAD定义的链表头指针;
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
TAILQ_FIRST((head))->field.tqe_prev = \
&TAILQ_NEXT((elm), field); \
else \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
TAILQ_FIRST((head)) = (elm); \
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
} while (0)
// 用于将元素elm插入到尾队列head的尾部;head是TAILQ_HEAD定义的链表头指针;
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
TAILQ_NEXT((elm), field) = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
} while (0)
// 用于获取尾队列的最后一个元素,headname是用户自定义的数据类型;
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
// 用于获取elm元素的下一个元素,field是前面用TAILQ_ENTRY定义的成员变量名;
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
// 用于获取elm元素的前面一个元素,headname是用户自定义的数据类型;
#define TAILQ_PREV(elm, headname, field) \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
// 用于尾队列head中删除elm元素;
#define TAILQ_REMOVE(head, elm, field) do { \
if ((TAILQ_NEXT((elm), field)) != NULL) \
TAILQ_NEXT((elm), field)->field.tqe_prev = \
(elm)->field.tqe_prev; \
else \
(head)->tqh_last = (elm)->field.tqe_prev; \
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
} while (0)
3,模型
4,验证例程
#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>
struct QUEUE_ITEM {
int value;
TAILQ_ENTRY(QUEUE_ITEM) entry;
};
static TAILQ_HEAD(,QUEUE_ITEM) queue_head;
int main(int argc, char *argv[])
{
int i = 0;
struct QUEUE_ITEM *item;
struct QUEUE_ITEM *tmp_item;
TAILQ_INIT(&queue_head);
if (TAILQ_EMPTY(&queue_head))
printf("queue is empty\n");
printf("after do TAILQ_INSERT_HEAD\n");
for( i = 0; i < 10; i ++) {
item = (struct QUEUE_ITEM *)malloc(sizeof(struct QUEUE_ITEM));
item->value = i;
TAILQ_INSERT_HEAD(&queue_head, item, entry);
}
TAILQ_FOREACH(tmp_item, &queue_head, entry)
printf("Has Item pointer = %p, item value = %d\n", tmp_item, tmp_item->value);
printf("after do TAILQ_INSERT_TAIL\n");
for( i = 0; i < 10; i ++) {
item = (struct QUEUE_ITEM *)malloc(sizeof(struct QUEUE_ITEM));
item->value = i + 10;
TAILQ_INSERT_TAIL(&queue_head, item, entry);
}
TAILQ_FOREACH(tmp_item, &queue_head, entry)
printf("Has Item pointer = %p, item value = %d\n", tmp_item, tmp_item->value);
printf("after do TAILQ_REMOVE\n");
TAILQ_FOREACH(tmp_item, &queue_head, entry) {
TAILQ_REMOVE(&queue_head, tmp_item, entry);
free(tmp_item);
}
if (TAILQ_EMPTY(&queue_head))
printf("queue is empty\n");
exit(EXIT_SUCCESS);
return 0;
}
六,Circular Queue,CIRCLEQ
俗称:环形队列
1,声明
// 用于定义一个环形队列数据结构体的头变量,该结构体有两个指针成员cqh_first和cqh_last,分别指向第一个type类型的数据结构,和最后一个type类型的数据结构;
#define CIRCLEQ_HEAD(name, type) \
struct name { \
struct type *cqh_first; /* first element */ \
struct type *cqh_last; /* last element */ \
}
// 用于在定义时初始化CIRCLEQ_HEAD定义的数据结构体的头变量;
#define CIRCLEQ_HEAD_INITIALIZER(head) \
{ (void *)&(head), (void *)&(head) }
// 则用于定义一个(用户)结构体的成员变量,该成员变量包含两个指向type类型的指针cqe_next和cqe_prev;
#define CIRCLEQ_ENTRY(type) \
struct { \
struct type *cqe_next; /* next element */ \
struct type *cqe_prev; /* previous element */ \
}
2,函数
// 用于判断环形队列是否为空:空则返回true,否则返回false;
#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
// 用于获取环形队列的第一个元素;
#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
// 用于正向遍历环形队列,var是临时变量,head是链表头指针(CIRCLEQ_HEAD定义的变量指针),field是CIRCLEQ_ENTRY定义的成员变量名;
#define CIRCLEQ_FOREACH(var, head, field) \
for ((var) = CIRCLEQ_FIRST((head)); \
(var) != (void *)(head) || ((var) = NULL); \
(var) = CIRCLEQ_NEXT((var), field))
// 用于逆向遍历环形队列,var是临时变量,head是链表头指针(CIRCLEQ_HEAD定义的变量指针),field是CIRCLEQ_ENTRY定义的成员变量名;
#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
for ((var) = CIRCLEQ_LAST((head)); \
(var) != (void *)(head) || ((var) = NULL); \
(var) = CIRCLEQ_PREV((var), field))
// 用于初始化CIRCLEQ_HEAD定义的头指针变量;当然也可以在使用CIRCLEQ_HEAD定义头指针变量时同时使用CIRCLEQ_HEAD_INITIALIZER进行初始化;
#define CIRCLEQ_INIT(head) do { \
CIRCLEQ_FIRST((head)) = (void *)(head); \
CIRCLEQ_LAST((head)) = (void *)(head); \
} while (0)
// 用于将元素elm插入到环形队列head的listelm元素后面;head是CIRCLEQ_HEAD定义的链表头指针;
#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
CIRCLEQ_NEXT((elm), field) = CIRCLEQ_NEXT((listelm), field); \
CIRCLEQ_PREV((elm), field) = (listelm); \
if (CIRCLEQ_NEXT((listelm), field) == (void *)(head)) \
CIRCLEQ_LAST((head)) = (elm); \
else \
CIRCLEQ_PREV(CIRCLEQ_NEXT((listelm), field), field) = (elm);\
CIRCLEQ_NEXT((listelm), field) = (elm); \
} while (0)
// 用于将元素elm插入到环形队列head的listelm元素前面;head是CIRCLEQ_HEAD定义的链表头指针;
#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
CIRCLEQ_NEXT((elm), field) = (listelm); \
CIRCLEQ_PREV((elm), field) = CIRCLEQ_PREV((listelm), field); \
if (CIRCLEQ_PREV((listelm), field) == (void *)(head)) \
CIRCLEQ_FIRST((head)) = (elm); \
else \
CIRCLEQ_NEXT(CIRCLEQ_PREV((listelm), field), field) = (elm);\
CIRCLEQ_PREV((listelm), field) = (elm); \
} while (0)
// 用于将元素elm插入到环形队列head的头部;head是CIRCLEQ_HEAD定义的链表头指针;
#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
CIRCLEQ_NEXT((elm), field) = CIRCLEQ_FIRST((head)); \
CIRCLEQ_PREV((elm), field) = (void *)(head); \
if (CIRCLEQ_LAST((head)) == (void *)(head)) \
CIRCLEQ_LAST((head)) = (elm); \
else \
CIRCLEQ_PREV(CIRCLEQ_FIRST((head)), field) = (elm); \
CIRCLEQ_FIRST((head)) = (elm); \
} while (0)
// 用于将元素elm插入到环形队列head的尾部;head是CIRCLEQ_HEAD定义的链表头指针;
#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
CIRCLEQ_NEXT((elm), field) = (void *)(head); \
CIRCLEQ_PREV((elm), field) = CIRCLEQ_LAST((head)); \
if (CIRCLEQ_FIRST((head)) == (void *)(head)) \
CIRCLEQ_FIRST((head)) = (elm); \
else \
CIRCLEQ_NEXT(CIRCLEQ_LAST((head)), field) = (elm); \
CIRCLEQ_LAST((head)) = (elm); \
} while (0)
// 用于获取环形队列的最后一个元素;
#define CIRCLEQ_LAST(head) ((head)->cqh_last)
// 用于获取elm元素的下一个元素,field是前面用CIRCLEQ_ENTRY定义的成员变量名;
#define CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next)
// 用于获取elm元素的上一个元素,field是前面用CIRCLEQ_ENTRY定义的成员变量名;
#define CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev)
// 用于环形队列head中删除elm元素;
#define CIRCLEQ_REMOVE(head, elm, field) do { \
if (CIRCLEQ_NEXT((elm), field) == (void *)(head)) \
CIRCLEQ_LAST((head)) = CIRCLEQ_PREV((elm), field); \
else \
CIRCLEQ_PREV(CIRCLEQ_NEXT((elm), field), field) = \
CIRCLEQ_PREV((elm), field); \
if (CIRCLEQ_PREV((elm), field) == (void *)(head)) \
CIRCLEQ_FIRST((head)) = CIRCLEQ_NEXT((elm), field); \
else \
CIRCLEQ_NEXT(CIRCLEQ_PREV((elm), field), field) = \
CIRCLEQ_NEXT((elm), field); \
} while (0)
3,模型
4,验证例程
#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>
struct QUEUE_ITEM {
int value;
CIRCLEQ_ENTRY(QUEUE_ITEM) entry;
};
static CIRCLEQ_HEAD(,QUEUE_ITEM) queue_head;
int main(int argc, char *argv[])
{
int i = 0;
struct QUEUE_ITEM *item;
struct QUEUE_ITEM *tmp_item;
CIRCLEQ_INIT(&queue_head);
if (CIRCLEQ_EMPTY(&queue_head))
printf("queue is empty\n");
printf("after do CIRCLEQ_INSERT_HEAD:\n");
for( i = 0; i < 10; i ++) {
item = (struct QUEUE_ITEM *)malloc(sizeof(struct QUEUE_ITEM));
item->value = i;
CIRCLEQ_INSERT_HEAD(&queue_head, item, entry);
}
CIRCLEQ_FOREACH(tmp_item, &queue_head, entry)
printf("Has Item pointer = %p, item value = %d\n", tmp_item, tmp_item->value);
printf("after do CIRCLEQ_INSERT_BEFORE:\n");
for( i = 0; i < 10; i ++) {
tmp_item = (struct QUEUE_ITEM *)malloc(sizeof(struct QUEUE_ITEM));
tmp_item->value = i + 10;
CIRCLEQ_INSERT_BEFORE(&queue_head, item, tmp_item, entry);
item = tmp_item;
}
CIRCLEQ_FOREACH(tmp_item, &queue_head, entry)
printf("Has Item pointer = %p, item value = %d\n", tmp_item, tmp_item->value);
CIRCLEQ_FOREACH(tmp_item, &queue_head, entry) {
CIRCLEQ_REMOVE(&queue_head, tmp_item, entry);
}
CIRCLEQ_FOREACH(tmp_item, &queue_head, entry)
printf("Has Item pointer = %p, item value = %d\n", tmp_item, tmp_item->value);
if (CIRCLEQ_EMPTY(&queue_head))
printf("queue is empty\n");
exit(EXIT_SUCCESS);
return 0;
}