contiki之list標頭檔案
阿新 • • 發佈:2018-12-01
contiki裡有很多基礎的資料結構和對應的操作函式,比如說記憶體管理memb,列表list 佇列queuebuff等等。如果不把這些最基礎的東西啃下的話,你去看上層的協議比如說ipv6 ,rpl等,那是寸步難行,根本不知道在幹嘛。接下來打算把這些資料結構挨個過一遍。接下來翻list的原始碼吧。
/***************************list.h**********************************/
#define LIST_CONCAT2(s1, s2) s1##s2
#define LIST_CONCAT(s1, s2) LIST_CONCAT2(s1, s2)
這兩個巨集就是用來拼接的,待會就會看到怎麼用。
#define LIST(name) \
static void *LIST_CONCAT(name,_list) = NULL; \
static list_t name = (list_t)&LIST_CONCAT(name,_list)
這個巨集用來定義兩個跟連結串列有關的指標,用一開始LIST_CONCAT巨集展開的話就是
static void* name_list = NULL
static list_t name = (list_t)&name_list
這個list_t又是啥,追蹤下去發現是
typedef void ** list_t; 也就是說定義了一個指標叫name_list,還有一個指向指標的指標name
#define LIST_STRUCT(name) \
void *LIST_CONCAT(name,_list); \
list_t name
這巨集定義跟上面的很像,關鍵就是少了個static,看註釋上也是說上面的巨集定義的是模組內部使用的靜態變數,這個巨集定義的是全域性。其實還不僅如此,我搜了一下用到這個巨集的地方,在uip-ds6-route.h裡有,如下
struct uip_ds6_route_neighbor_routes {
LIST_STRUCT(route_list);
};
而LIST這個巨集在nbr_table.c裡是這樣的
LIST(nbr_table_keys);
也就是說用LIST的時候定義的是兩個零散的變數,用LIST_STRUCT的時候變數是被裝在一個結構體裡的。好,接著往下看。
#define LIST_STRUCT_INIT(struct_ptr, name) \
do { \
(struct_ptr)->name = &((struct_ptr)->LIST_CONCAT(name,_list)); \
(struct_ptr)->LIST_CONCAT(name,_list) = NULL; \
list_init((struct_ptr)->name); \
} while(0)
這個巨集呢就是用來給
LIST_STRUCT巨集定義的結構體初始化用的。這樣看可能不是很清楚這個巨集的原理,結合例項看就明白了。在uip-ds6-route.c裡有如下語句
struct uip_ds6_route_neighbor_routes *routes;
LIST_STRUCT_INIT(routes, route_list);
uip_ds6_route_neighbor_routes就是包含了
LIST_STRUCT的結構體型別。
list_init((struct_ptr)->name)這句感覺是多餘的,跟
(struct_ptr)->LIST_CONCAT(name,_list) = NULL是一樣的。
接下來老規矩,就是一堆針對這個list資料結構的操作函式聲明瞭。
void list_init(list_t list);
void * list_head(list_t list);
void * list_tail(list_t list);
void * list_pop (list_t list);
void list_push(list_t list, void *item);
void * list_chop(list_t list);
void list_add(list_t list, void *item); void list_remove(list_t list, void *item);
int list_length(list_t list);
void list_copy(list_t dest, list_t src);
void list_insert(list_t list, void *previtem, void *newitem);
void * list_item_next(void *item);
#endif /* LIST_H_ */ 你可能覺得怪怪的,這個list結構體有點空蕩蕩的,就一個指標還有一個指向這個指標的指標,就兩個變數而已,算什麼列表?別急,看了list.c就會明白,這個list的適用面很廣,設計得很靈活。
void * list_chop(list_t list);
void list_add(list_t list, void *item); void list_remove(list_t list, void *item);
int list_length(list_t list);
void list_copy(list_t dest, list_t src);
void list_insert(list_t list, void *previtem, void *newitem);
void * list_item_next(void *item);
#endif /* LIST_H_ */ 你可能覺得怪怪的,這個list結構體有點空蕩蕩的,就一個指標還有一個指向這個指標的指標,就兩個變數而已,算什麼列表?別急,看了list.c就會明白,這個list的適用面很廣,設計得很靈活。