3. 可以考虑动态增长空间,不断加入新的一阶,且对原来的数据没影响。
二、使用共享内存的多级哈希表的一种实现
在一个服务程序运行的时候,它往往要把数据写入共享内存以便在进城需要重新启动的时候可以直接从共享内存中读取数据,另一方面,在服务进程因某种原因挂掉的时候,共享内存中的数据仍然存在,这样就可以减少带来的损失。关于共享内存的内容请google之,在这里,实现了一种在共享内存中存取数据的hash表,它采用了多级存储求模取余的方法,具体内容请看以下代码:
//hash_shm.h
/*
一个锯齿数组,每一行都是素数,从多到少
* * * * * *
* * * * *
* * * *
* * *
* *
*
*/
#ifndef _STORMLI_HASH_SHM_H_
#define _STORMLI_HASH_SHM_H_
#include
#include
#include
#include
//#include
using namespace std;
template
class hash_shm
{
public:
int find(unsigned long _key); //if _key in the table,return 0,and set lastFound the position,otherwise return -1
int remove(unsigned long _key); //if _key not in the table,return-1,else remove the node,set the node key 0 and return 0
//insert node into the table,if the _key exists,return 1,if insert success,return 0;and if fail return -1
int insert(unsigned long _key,const valueType &_value);
void clear(); //remove all the data
public: //some statistic function
double getFullRate()const; //the rate of the space used
public:
//constructor,with the share memory start position and the space size,if the space is not enough,the program will exit
hash_shm(void *startShm,unsigned long shmSize=sizeof(hash_node)*maxLine*lines);
//constructor,with the share memory key,it will get share memory,if fail,exit
//hash_shm(key_t shm_key);
~hash_shm(){} //destroy the class
void foreach(void (*fn)(unsigned long _key,valueType &_value));
private:
void *mem; //the start position of the share memory // the mem+memSize space used to storage the runtime data:currentSize
unsigned long memSize; //the size of the share memory
unsigned long modTable[lines]; //modtable,the largest primes, hash表的阶,为每一阶产生一个素数
unsigned long modTotal[lines]; //modTotal[i] is the summary of the modTable
unsigned long maxSize; //the size of the table
unsigned long *currentSize; //current size of the table ,the pointer of the shm mem+memSize
void *lastFound; //write by the find function,record the last find place
struct hash_node{ //the node of the hash table
unsigned long key; //when key==0,the node is empty
valueType value; //name-value pair
};
private:
//bool getShm(key_t shm_key); //get share memory,used by the constructor
void getMode(); //get the largest primes blow maxLine,use by the constructor
void *getPos(unsigned int _row,unsigned long _col);//get the positon with the (row,col)
};
template
hash_shm::hash_shm(void *startShm,unsigned long shmSize)
{
if(startShm!=NULL){
cerr<<"Argument error\n Please check the shm address\n";
exit(-1);
}
getMode();
maxSize=0;
int i;
for(i=0;i
hash_shm::hash_shm(key_t shm_key)
{ //constructor with get share memory
getMode();
maxSize=0;
for(int i=0;i
int hash_shm::find(unsigned long _key)
{
unsigned long hash;
hash_node *pH=NULL;
for(int i=0;ikey==_key){
lastFound=pH;
return 0;
}
//如果hash冲突,继续在下一阶查找
}
return -1;
}
/// 删除一个元素,仅仅标记这个节点的key为0即可
template
int hash_shm::remove(unsigned long _key)
{
if(find(_key)==-1)return -1; //not found
hash_node *pH=(hash_node *)lastFound;
pH->key=0; //only set the key 0
(*currentSize)--;
return 0;
}
template
int hash_shm::insert(unsigned long _key,const vT &_value)
{
if(find(_key)==0)return 1; //if the key exists
unsigned long hash;
hash_node *pH=NULL;
for(int i=0;ikey==0){ //find the insert position,insert the value
pH->key=_key;
pH->value=_value;
(*currentSize)++;
return 0;
}
}
return -1; //all the appropriate position filled
}
template
void hash_shm::clear()
{
memset(mem,0,memSize);
*currentSize=0;
}
/*
template
bool hash_shm::getShm(key_t shm_key)
{
int shm_id=shmget(shm_key,memSize,0666);
if(shm_id==-1) //check if the shm exists
{
shm_id=shmget(shm_key,memSize,0666|IPC_CREAT);//create the shm
if(shm_id==-1){
cerr<<"Share memory get failed\n";
return false;
}
}
mem=shmat(shm_id,NULL,0); //mount the shm
if(int(mem)==-1){
cerr<<"shmat system call failed\n";
return false;
}
return true;
}
*/
/// vT value的数据类型
/// maxLine 每阶的最大元素个数
/// lines hash的阶
/// 为每一阶产生一个素数
/// 素数从大到小的排列
template
void hash_shm::getMode()
{ //采用 6n+1 6n-1 素数集中原理
// 每阶至少5个元素
if(maxLine<5){exit(-1);}
unsigned long t,m,n,p;
int i,j,a,b,k;
int z=0;
// 1000/6 = 166
// 找166到0之间的所有素数吗?
for(t=maxLine/6;t>=0,z= lines)return;}
if(i){modTable[z++]=m-1;if(z>= lines)return;}
}
}
template
void *hash_shm::getPos(unsigned int _row,unsigned long _col)
{
//unsigned long pos=0UL;
//for(int i=0;i<_row;i++) //calculate the positon from the start
// pos+=modTable[i];
//pos+=_col;
unsigned long pos=_col+modTotal[_row];
if(pos>=maxSize)return NULL;
return (void *)((long)mem+pos*sizeof(hash_node));
}
/// 占用百分比
template
double hash_shm::getFullRate()const
{
return double(*currentSize)/maxSize;
}
template
void hash_shm::foreach(void (*fn)(unsigned long _key,vT &_value))
{
typedef unsigned long u_long;
u_long beg=(u_long)mem;
u_long end=(u_long)mem+sizeof(hash_node)*(modTable[lines-1]+modTotal[lines-1]);
hash_node *p=NULL;
for(u_long pos=beg;poskey!=0)fn(p->key,p->value);
}
}
#endif
/*
g++ -o hash_shm_1.h.gch -x c++-header -c hash_shm_1.h -g
*/
int find(unsigned long _key,vT &_value);
//test.cpp
#include"hash_shm.h"
#include
using namespace std;
int main()
{
hash_shm ht(key_t(999));
double rate=0.0;
// ht.clear();
for(int i=0;i<100;i++){
srand(time(NULL)+i);
while(true){
if(ht.insert(rand(),0)==-1)break;
}
cout<
摘自:
原文