NS2中的链表采用了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 */ \
}
/*
* List functions.
*/
#define LIST_INIT(head) { \
(head)->lh_first = NULL; \
}
#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; \
}
#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; \
}
#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; \
}
NS中大量使用了链表,因为所有的网络节点需要用链表串起来,然后才可以进行遍历,而每个节点可能具有多个链路头LinkHead和接口Phy(这里节点Node与LinkHead和Phy的if的关系还没搞太清除),这些LinkHead也要用链表串起来,用于遍历后,形成网络拓扑,然后计算路由。
所有的type都是链表元素的指针,比如节点的链表的type就是节点的指针,LinkHead链表的type就是LinkHead。
LIST_HEAD(name, type)
定义一个链表头结构体,注意只是定义结构体,还没有声明链表头结构体 变量,这个需要在类的变量中进行定义。
对于Node类,因为需要将所有Node类实例化的对象串成链表,链表头属于Node类的属性,不是任何一个Node对象的属性,所以用静态变量定义:
static struct node_head nodehead_; // static head of list of nodes
而对于LinkHead的链表头则是Node下的一个属性,不用定义为静态变量
定义完链表头结构体,定义完链表头结构体变量,下一步是初始化链表头结构体变量,即
#define LIST_INIT(head)
这个仅仅是将链表头赋初值NULL。
这里需要注意的是对于Node的链表头变量是静态变量,静态变量的在类中仅仅是声明,还需要定义,而定义不能在实例化的过程中完成,需要单独完成,定义的同时,进行初始化:
struct node_head Node::nodehead_ = { 0 }; // replaces LIST_INIT macro
而LinkHead和if则可以直接在Node的构造函数中,使用list的宏进行初始化
LIST_INIT(&ifhead_);
LIST_INIT(&linklisthead_);
#define LIST_ENTRY(type)
ENTRY表项宏,就是在类中加了两个指针,从而使类能够前后关联串起来成为链表
由于只是使用单向链表,所以插入元素只是使用了在Head插入。
最后,还要在Node类中定义两个函数,一个是将自己加入到链表中,一个是返回下一个链表元素:
inline void insert(struct node_head* head) {
LIST_INSERT_HEAD(head, this, entry);
}
inline Node* nextnode() { return entry.le_next; }
对于Node下的链路LinkHead和接口Phy if的关系还没太搞清楚,得再看看!