Queue学习之Singly-Linked List

早就听说了libevent这个开源网络库的大名,刚好最近时间比较闲,所以就拜读一下。计划是从0.1版本(最早版)开始看起,因为我想看一下libevent成长历史和网络通信方面的相关技术发展。在libevent0.1版本中,核心就是event这个结构体了。而这个结构体中又用了sys/queue.h中的TAIL QUEUES。因此打算先学习一下sys/queue.h中提到的几个queue。本文将会讲解一下sys/queue.h中的Singly-Linked-Lists

singly-linked list有一个SLIST_HEAD宏定义的结构作为链表头。这个结构包含一个指向该单向链表第一个元素的指针。单向链接的元素具有最小的空间,移除任意元素的指针操作开销为O(n)。新元素可以加在链表中已存在元素的后面或者在链表的头部。

单向链表的宏定义

/*
 * Singly-linked List definitions.
 */
#define SLIST_HEAD(name, type) \
struct name {                               \
    struct type *slh_first; /* first element */         \
}

#define SLIST_HEAD_INITIALIZER(head) \
    { NULL }

#define SLIST_ENTRY(type) \
struct {                                \
    struct type *sle_next;  /* next element */          \
}

/*
 * Singly-linked List access methods.
 */
#define SLIST_FIRST(head) ((head)->slh_first)
#define SLIST_END(head) NULL
#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)

#define SLIST_FOREACH(var, head, field) \
    for((var) = SLIST_FIRST(head);                  \
        (var) != SLIST_END(head);                   \
        (var) = SLIST_NEXT(var, field))

/*
 * Singly-linked List functions.
 */
#define SLIST_INIT(head) { \
    SLIST_FIRST(head) = SLIST_END(head);                \
}

#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
    (elm)->field.sle_next = (slistelm)->field.sle_next;     \
    (slistelm)->field.sle_next = (elm);             \
} while (0)

#define SLIST_INSERT_HEAD(head, elm, field) do { \
    (elm)->field.sle_next = (head)->slh_first;          \
    (head)->slh_first = (elm);                  \
} while (0)

#define SLIST_REMOVE_HEAD(head, field) do { \
    (head)->slh_first = (head)->slh_first->field.sle_next;      \
} while (0)

SLIST_HEAD 结构定义如下:

SLIST_HEAD(HEADNAME, TYPE) head;

HEADNAME是要定义的单链表头结构体的名字,TYPE是链表中的元素类型。下面就是定义了一个单链表头的指针:

struct HEADNAME *headp;

SLIST_ENTRY宏声明了一个连接单链表内元素的结构体
SLIST_INIT宏通过参数head初始化单链表
SLIT_INSERT_HEAD宏在单链表的头部插入一个元素elm
SLIST_INSERT_AFTER宏插入一个新元素elm
SLIST_REMOVE_HEAD宏从单链表头部移除元素elm
SLIST_REMOVE宏从单链表中移除elm

单向链表的例子

LIST_HEAD(slisthead, entry) head;
struct slisthead *headp;        /* 单向链表头部 */
struct entry {
    SLIST_ENTRY(entry) entries;     /* 单向链表 */
    int data;
} *n1, *n2, *n3, *np;

SLIST_INIT(&head);      /* 初始化链表 */

n1 = malloc(sizeof(struct entry));      /* 插入到头部 */
SLIST_INSERT_HEAD(&head, n1, entries);

n2 = malloc(sizeof(struct entry));      /* 插入n1后面 */
SLIST_INSERT_AFTER(n1, n2, entries);

SLIST_REMOVE(&head, n2, entry, entries);        /* 移除n2 */
free(n2);

n3 = head.slh_first;        /* 移除头部元素 */
SLIST_REMOVE_HEAD(&head, entries);
free(n3);

for (np = head.slh_first; np != NULL; np = np->entries.sle_next)        /* 遍历 */
    np->data = 1;

while (head.slh_first != NULL) {
    n1 = head.slh_first;
    SLIST_REMOVE_HEAD(&head, entries);
    free(n1);
}

参考资料

GNO:queue(3)

你可能感兴趣的:(网络,libevent,queue-h)