bsd-list.h 注释说明

来源:互联网 发布:ubuntu apt get 路径 编辑:程序博客网 时间:2024/05/16 01:10

作者:lzqlgq@gmail.com


我们在NS2中的基类中经常会看到宏LIST_HEAD,LIST_ENTRY等宏,它们实现此类的实体的链表,举一个例子Node类就是一个例子, 在node.h中有如下定义有如下代码

 注意: 代码省略了不相关部分代码
 LIST_HEAD(node_head, Node);

 // 声明链表的头节点结构体 node_head,仅含有Node 型指针 lh_first 一个

        class Node : public ParentNode {

        public:

            static struct node_head nodehead_; // static head of list of nodes

            inline void insert(struct node_head* head) {

                LIST_INSERT_HEAD(head, this, entry);

            }

            inline Node* nextnode() { return entry.le_next; }

        protected:

            LIST_ENTRY(Node) entry;

        // 声明链表指针实体部分,含有两个指针

        }


Node类的实例可以通过结构体变量entry里包含的两个Node*类型的指针来链接成一个链表。


由于NS 软件的特点,我们经常需要读各种组件的代码,以及修改代码,这样对于常用的结构我们必须了解,比如在函数dump中的ifhead_.lh_first,如果我们每次遇到这样的结构都去查找,那么工作量会很大,并且会发现我们总是需要跳转多个文件才可一最终弄通当前的代码含义。


void MobileNode::dump(void)

{

    Phy *n;

    fprintf(stdout, "Index: %d/n", address_);

    fprintf(stdout, "Network Interface List/n");

    for(n = ifhead_.lh_first; n; n = n->nextnode() )

    n->dump();

    fprintf(stdout,/ "--------------------------------------------------/n");

}

所以了解这些宏的含义,和系统已经定义的各种宏就很有必要,下边我们介绍宏的定义以及代码分析。

二、宏定义说明:

ns2里最常用的宏链表定义在文件ns-2.31/lib/bsd-list.h 中,其功能很是大,下边是详细代码分析

//头节点宏

//链表单指针头节点结构体宏

#define LIST_HEAD(name, type)

struct name {

type *lh_first; /* first element */

}


//链表实体用于连接的指针部分、 可在某个类的定义中声明该结构题的实体,就可以用此链表连接此类的实体了

#define LIST_ENTRY(type)

struct {

type *le_next;/* next element */

type **le_prev;/* address of previous next element */

// le_next指向下一个节点,le_prev指向前面节点的 “next element” 的地址,“next elemnet “ lh_first或者 le_next这样用发就同一了接口,实在是高

}

//初始化连表 struct name * head

#define LIST_INIT(head) {

(head)->lh_first = NULL;

}

/* 变量说明:

  • struct name * head,指向链表的头节点

  • listelm, elm为指向一个类/实体的指针

  • field为此elmLIST_ENTRY实体

  • 特别注意 le_prev的处理与众不同,他是二级 指针变量

*/

// 尾插法 elm插入到 listelm后 使用的指针在field

#define LIST_INSERT_AFTER(listelm, elm, field) {

if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)

(listelm)->field.le_next->field.le_prev =

&(elm)->field.le_next;

(listelm)->field.le_next = (elm);

(elm)->field.le_prev = &(listelm)->field.le_next;

}

// 前插法 ,elm插入到listelm

#define LIST_INSERT_BEFORE(listelm, elm, field) {

(elm)->field.le_prev = (listelm)->field.le_prev;

(elm)->field.le_next = (listelm);

*(listelm)->field.le_prev = (elm);

(listelm)->field.le_prev = &(elm)->field.le_next;

}

// 头插法 elm插入到head后边

#define LIST_INSERT_HEAD(head, elm, field) {

if (((elm)->field.le_next = (head)->lh_first) != NULL)

(head)->lh_first->field.le_prev = &(elm)->field.le_next;

(head)->lh_first = (elm);

(elm)->field.le_prev = &(head)->lh_first;//指向指针的指针

}

// 删除elm,由于是双向链表,参数只有两个就可以了

#define LIST_REMOVE(elm, field) {

if ((elm)->field.le_next != NULL)

(elm)->field.le_next->field.le_prev =

(elm)->field.le_prev;

*(elm)->field.le_prev = (elm)->field.le_next;

}

原创粉丝点击