栗子如下:
#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