侵入式链表实现

2021-03-27  本文已影响0人  wayyyy

先来看2个宏

#define offset(struct_type, member) (int)(&((struct_type*)0)->member)

假设:
struct Foo
{
    int a;
    int b;
    Foo* next;
};

offset(struct Foo, a);    // 0
offset(struct Foo, b);    // 4
offset(struct Foo, next); // 8 

offset 宏的目的是推算出一个成员的偏移量。

Foo.png

(struct_type*)0 将0x0 强制转为struct_type的首地址。
((struct_type*)0)->member)为目标成员。
(int)(&((struct_type*)0)->member))将目标成员取地址,因为是从0x0开始,所以这个地址也就恰好成为了目标成员的偏移地址。

#define elem2entry(struct_type, struct_member_name, elem_ptr) \
     (struct_type*)((int)elem_ptr - offset(struct_type, struct_member_name))

假设:
struct link 
{
    struct link* next;
};

struct Foo
{
    int a; 
    struct link link_tag;
};

struct Foo foo;
foo.a = 20; foo.link_tag.next = NULL;
    
struct link* linkptr = &(foo.link_tag);
 
struct Foo* fp = elem2entry(struct Foo, link_tag, linkptr);
   
printf("%d\n", fp->a);
image.png
struct list_elem
{
    struct list_elem* prev;
    struct list_elem* next;
};

/* 实现队列 */
struct list
{
    struct list_elem head;  // head 队首,固定不变. 第一个元素是head.next
    struct list_elem tail;  // tail 队尾,固定不变.
};
/* 初始化双向链表 */
void list_init(struct list* list)
{
    list->head.prev = NULL;
    list->head.next = &(list->tail);
    list->tail.prev = &(list->head);
    list->tail.next = NULL;
}
image.png
void list_insert_before(struct list_elem* before, struct list_elem* elem)
{
    before->prev->next = elem;

    elem->prev = before->prev;
    elem->next = before;

    before->prev = elem;
}

/* 添加元素到列表队首,类似push_front操作 */
void list_push(struct list* plist, struct list_elem* elem)
{
    list_insert_before(plist->head.next, elem);
}

/* 追加元素到链表队尾,类似队列的先进先出操作 */
void list_append(struct list* plist, struct list_elem* elem)
{
    list_insert_before(&(plist->tail), elem);
}
/* 使元素pelem脱离链表 */
void list_remove(struct list_elem* pelem)
{
    // 实现原子操作,关掉中断
    enum intr_status old_status = intr_disable();

    pelem->prev->next = pelem->next;
    pelem->next->prev = pelem->prev;

    intr_set_status(old_status);
}

/* 将链表第一个元素弹出并返回 */
struct list_elem* list_pop(struct list* plist)
{
    struct list_elem* elem = plist->head.next;
    list_remove(elem);
    return elem;
}
上一篇下一篇

猜你喜欢

热点阅读