linux核心 hash表的基本使用
阿新 • • 發佈:2018-12-07
栗子如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "hlist.h" typedef struct list_test{ struct hlist_node hnode; int ap; }HlistTest; //計算hash值 struct hlist_head * call_hash(struct hlist_head *hash,int id) { unsigned int val = id % 8; return &hash[val]; } int main(int argc,char *argv[]) { struct hlist_head *hash; struct hlist_node *p = NULL,*n=NULL; int i = 0; HlistTest *pNode; //建立hash表頭 hash = (struct hlist_head *)malloc(sizeof(*hash)*8); if(NULL == hash) { printf("alloc error\n"); return -1; } //初始化hash表頭 for(i = 0; i<8; i++) INIT_HLIST_HEAD(&hash[i]); //對hash節點賦值 for(i = 0; i<100;i++) { pNode = (HlistTest *)malloc(sizeof(HlistTest)); if(pNode == NULL) continue; memset(pNode,0,sizeof(HlistTest)); INIT_HLIST_NODE(&pNode->hnode); pNode->ap = i; hlist_add_head(&pNode->hnode, call_hash(hash,i)); } //輸出key為3的所有節點 hlist_for_each_safe(p,n,call_hash(hash,3) ){ pNode = hlist_entry(p, HlistTest, hnode); if(pNode != NULL) printf("%d\n",pNode->ap); } //刪除所有的hash節點 for(i = 0; i<8;i++) { p = n = NULL; hlist_for_each_safe(p,n,&hash[i]) { pNode = hlist_entry(p, HlistTest, hnode); hlist_del(&pNode->hnode); free(pNode); } } //節點刪除後 看是否還能輸出key為3的所有節點 printf("After delete node\n"); hlist_for_each_safe(p,n,call_hash(hash,3) ){ pNode = hlist_entry(p, HlistTest, hnode); if(pNode != NULL) printf("%d\n",pNode->ap); } out: free(hash); return 0; }
hlist.h
#ifndef __HLIST_H #define __HLIST_H struct hlist_head { struct hlist_node *first; }; struct hlist_node { struct hlist_node *next, **pprev; }; #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) #define HLIST_HEAD_INIT { .first = NULL } #define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } #define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) static inline void INIT_HLIST_NODE(struct hlist_node *h) { h->next = NULL; h->pprev = NULL; } static inline int hlist_unhashed(const struct hlist_node *h) { return !h->pprev; } static inline int hlist_empty(const struct hlist_head *h) { return !h->first; } static inline void __hlist_del(struct hlist_node *n) { struct hlist_node *next = n->next; struct hlist_node **pprev = n->pprev; *pprev = next; if (next) next->pprev = pprev; } static inline void hlist_del(struct hlist_node *n) { __hlist_del(n); n->next = NULL; n->pprev = NULL; } static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) { struct hlist_node *first = h->first; n->next = first; if (first) first->pprev = &n->next; h->first = n; n->pprev = &h->first; } static inline void hlist_del_init(struct hlist_node *n) { if (!hlist_unhashed(n)) { __hlist_del(n); INIT_HLIST_NODE(n); } } static inline void hlist_add_before(struct hlist_node *n, struct hlist_node *next) { n->pprev = next->pprev; n->next = next; next->pprev = &n->next; *(n->pprev) = n; } static inline void hlist_add_after(struct hlist_node *n, struct hlist_node *next) { next->next = n->next; n->next = next; next->pprev = &n->next; if(next->next) next->next->pprev = &next->next; } static inline void hlist_move_list(struct hlist_head *old, struct hlist_head *new) { new->first = old->first; if (new->first) new->first->pprev = &new->first; old->first = NULL; } #define hlist_entry(ptr, type, member) container_of(ptr,type,member) #define hlist_for_each_safe(pos, n, head) \ for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ pos = n) #define hlist_for_each_entry(tpos, pos, head, member) \ for (pos = (head)->first; \ pos && ({ prefetch(pos->next); 1;}) && \ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ pos = pos->next) #define hlist_for_each_entry_continue(tpos, pos, member) \ for (pos = (pos)->next; \ pos && ({ prefetch(pos->next); 1;}) && \ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ pos = pos->next) #define hlist_for_each_entry_from(tpos, pos, member) \ for (; pos && ({ prefetch(pos->next); 1;}) && \ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ pos = pos->next) #define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ for (pos = (head)->first; \ pos && ({ n = pos->next; 1; }) && \ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ pos = n) #endif