1. 程式人生 > >linux核心 hash表的基本使用

linux核心 hash表的基本使用

栗子如下:

#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