• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            洗塵齋

            三懸明鏡垂鴻韻,九撩清泉洗塵心

            常用鏈接

            統計

            最新評論

            使用共享內存的多級哈希表的一種實現

            在一個服務程序運行的時候,它往往要把數據寫入共享內存以便在進城需要重新啟動的時候可以直接從共享內存中讀取數據,另一方面,在服務進程因某種原因掛掉的時候,共享內存中的數據仍然存在,這樣就可以減少帶來的損失。關于共享內存的內容請google之,在這里,實現了一種在共享內存中存取數據的hash表,它采用了多級存儲求模取余的方法,具體內容請看以下代碼:
            http://lmlf001.blog.sohu.com/


            //hash_shm.h
            #ifndef _STORMLI_HASH_SHM_H_
            #define _STORMLI_HASH_SHM_H_

            #include
            <iostream>
            #include
            <cstdlib>
            #include
            <cmath>
            #include
            <sys/shm.h>
            using namespace std;

            template
            <typename valueType,unsigned long maxLine,int lines>
            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
            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
                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
            <typename vT,unsigned long maxLine,int lines>
            hash_shm
            <vT,maxLine,lines>::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<lines;i++)    //count the maxSize
                    maxSize+=modTable[i];
                
            if(shmSize<sizeof(hash_node)*(maxSize+1)){    //check the share memory size
                    cerr<<"Not enough share memory space\n";
                    exit(
            -1);
                }
                memSize
            =shmSize;
                
            if(*(currentSize=(unsigned long *)((long)mem+memSize))<0)
                    
            *currentSize=0;;
            }

            template
            <typename vT,unsigned long maxLine,int lines>
            hash_shm
            <vT,maxLine,lines>::hash_shm(key_t shm_key)
            {    
            //constructor with get share memory
                getMode();
                maxSize
            =0;
                
            for(int i=0;i<lines;i++)
                    maxSize
            +=modTable[i];
                memSize
            =sizeof(hash_node)*maxSize;    
                
            if(!getShm(shm_key)){
                    exit(
            -1);
                }
            //    memset(mem,0,memSize);
                if(*(currentSize=(unsigned long *)((long)mem+memSize))<0)
                    
            *currentSize=0;
            }    


            template
            <typename vT,unsigned long maxLine,int lines>
            int hash_shm<vT,maxLine,lines>::find(unsigned long _key)
            {
                unsigned 
            long hash;
                hash_node 
            *pH=NULL;
                
            for(int i=0;i<lines;i++)
                {
                    hash
            =(_key+maxLine)%modTable[i];    //calculate the col position
                    pH=(hash_node *)getPos(i,hash);
            //        if(pH==NULL)return -2;    //almost not need
                    if(pH->key==_key){
                        lastFound
            =pH;
                        
            return 0;
                    }
                }
                
            return -1;
            }

            template
            <typename vT,unsigned long maxLine,int lines>
            int hash_shm<vT,maxLine,lines>::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
            <typename vT,unsigned long maxLine,int lines>
            int hash_shm<vT,maxLine,lines>::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;i<lines;i++){    
                    hash
            =(_key+maxLine)%modTable[i];
                    pH
            =(hash_node *)getPos(i,hash);
                    
            if(pH->key==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
            <typename vT,unsigned long maxLine,int lines>
            void hash_shm<vT,maxLine,lines>::clear()
            {
                memset(mem,
            0,memSize);
                
            *currentSize=0;
            }


            template
            <typename vT,unsigned long maxLine,int lines>
            bool hash_shm<vT,maxLine,lines>::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;
            }

            template
            <typename vT,unsigned long maxLine,int lines>
            void hash_shm<vT,maxLine,lines>::getMode()
            {        
            //采用 6n+1 6n-1 素數集中原理
                if(maxLine<5){exit(-1);}
                
                unsigned 
            long t,m,n,p;
                
            int i,j,a,b,k;
                
            int z=0;
                
                
            for(t=maxLine/6;t>=0,z<lines;t--)
                {
                    i
            =1;j=1; k=t%10;
                    m
            =6*t;                                        /**i,j的值 是是否進行驗證的標志也是對應的6t-1和6t+1的素性標志**/
                    
            if(((k-4)==0)||((k-9)==0)||((m+1)%3==0))j=0;/*此處是簡單驗證6*t-1,6*t+1 是不是素數,借以提高素數純度**/
                    
            if(((k-6)==0)||((m-1)%3==0))i=0;            /***先通過初步判斷去除末尾是5,及被3整除的數***/
                    
            for(p=1;p*6<=sqrt(m+1)+2;p++ )
                    {
                        n
            =p*6;                                    /**將6*p-1和6*p+1看作偽素數來試除*****/
                        k
            =p%10;
                        a
            =1;b=1;                                /**同樣此處a,b的值也是用來判斷除數是否為素數提高除數的素數純度**/
                        
            if(((k-4)==0)||((k-9)==0))a=0;
                        
            if(((k-6)==0))b=0;
                        
            if(i){                            /*如果i非零就對m-1即所謂6*t-1進行驗證,當然還要看除數n+1,n-1,素性純度*/
                            
            if(a){if((m-1)%(n+1)==0)i=0;}        /***一旦被整除就說明不是素數故素性為零即將i 賦值為零***/
                            
            if(b){if((m-1)%(n-1)==0)i=0;}
                        }
                        
            if(j){                           /**如果j非零就對m+1即所謂6*t+1進行驗證,當然還要看除數n+1,n-1,素性純度*/
                            
            if(a){if((m+1)%(n+1)==0)j=0;}         /***一旦被整除就說明不是素數故素性為零即將j 賦值為零***/
                            
            if(b){if((m+1)%(n-1)==0)j=0;}
                        }
                        
            if((i+j)==0)break;                     /**如果已經知道6*t-1,6*t+1都不是素數了那就結束試除循環***/
                    }
                    
            if(j){modTable[z++]=m+1;if(z>= lines)return;}
                    
            if(i){modTable[z++]=m-1;if(z>= lines)return;}
                }
            }

            template
            <typename vT,unsigned long maxLine,int lines>
            void *hash_shm<vT,maxLine,lines>::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;        
                
            if(pos>=maxSize)return NULL;
                
            return (void *)((long)mem+pos*sizeof(hash_node));
            }

            template
            <typename vT,unsigned long maxLine,int lines>
            double hash_shm<vT,maxLine,lines>::getFullRate()const
            {
                
            return double(*currentSize)/maxSize;
            }


            #endif



            //test.cpp

            #include
            "hash_shm.h"
            #include
            <cstdlib>
            using namespace std;
            int main()
            {
                hash_shm
            <int,1000,100> 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
            <<ht.getFullRate()<<endl;
                    rate
            +=ht.getFullRate();
                    ht.clear();
                }
                cout
            <<"\n\n\n";
                cout
            <<rate/100<<endl;
            }

            這段代碼作測試的時候發現了一些問題,用gprof查看函數時間的時候發現,getPos函數占用了大部分的執行時間,始主要的性能瓶頸,后來又新設立了一個數組,用來記錄每行開始時的位置,性能提高了很多,改動部分的代碼如下:
            template<typename valueType,unsigned long maxLine,int lines>
            class hash_shm
            {

            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
                unsigned long modTotal[lines];    //modTotal[i] is the summary of the modTable when x<=i  
                                
            //used by getPos to improve the performance
                ...
            };

            template
            <typename vT,unsigned long maxLine,int lines>
            hash_shm
            <vT,maxLine,lines>::hash_shm(void *startShm,unsigned long shmSize)
            {
                ...

                
                
            int i;
                
            for(i=0;i<lines;i++){    //count the maxSize
                    maxSize+=modTable[i];
                    
            if(i!=0)modTotal[i]=modTotal[i-1]+modTable[i-1];
                    
            else modTotal[i]=0;    //caculate the modTotal
                }
                ...
            }

            template
            <typename vT,unsigned long maxLine,int lines>
            hash_shm
            <vT,maxLine,lines>::hash_shm(key_t shm_key)
            {    
            //constructor with get share memory 
                getMode();
                maxSize
            =0;
                
            for(int i=0;i<lines;i++){
                    maxSize
            +=modTable[i];
                    
            if(i!=0)modTotal[i]=modTotal[i-1]+modTable[i-1];
                    
            else modTotal[i]=0;
                }
                ...
            }    




            template
            <typename vT,unsigned long maxLine,int lines>
            void *hash_shm<vT,maxLine,lines>::getPos(unsigned int _row,unsigned long _col)
            {
                unsigned 
            long pos=_col+modTotal[_row];
                
            //for(int i=0;i<_row;i++)    //calculate the positon from the start
                
            //    pos+=modTable[i];
                if(pos<maxSize)
                    
            return (void *)((long)mem+pos*sizeof(hash_node));
                
            return NULL;    
            }


            新增了一個用于遍歷的函數foreach

            template<typename vT,unsigned long maxLine,int lines>
            void hash_shm<vT,maxLine,lines>::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;pos<end;pos+=sizeof(hash_node))
                {
                    p
            =(hash_node *)pos;
                    
            if(p->key!=0)fn(p->key,p->value);
                }
            }

            為了利于使用新增一個用于查找的函數find,該函數同find(_key)類似,如果找到_key節點,把它賦給_value以返回
            int find(unsigned long _key,vT &_value);

            posted on 2007-09-08 21:17 芥之舟 閱讀(7679) 評論(3)  編輯 收藏 引用 所屬分類: 數據結構和算法

            評論

            # re: 使用共享內存的多級哈希表的一種實現 2012-06-16 16:44 ydsec

            不錯,能發進一步改進,value如果是一個結構體,如何實現呢?內存用格式表示數據  回復  更多評論   

            # re: 使用共享內存的多級哈希表的一種實現 2014-08-28 13:14 null

            if(*(currentSize=(unsigned long *)((long)mem+memSize))<0)
            這一句不是很明白,  回復  更多評論   

            # re: 使用共享內存的多級哈希表的一種實現 2014-10-13 10:51 abc

            p*6<=sqrt(m+1)+2 這個是什么原理?  回復  更多評論   

            99久久精品免费看国产一区二区三区| 日韩十八禁一区二区久久| 久久国产精品99国产精| 国产精品9999久久久久| 久久av高潮av无码av喷吹| 亚洲综合熟女久久久30p| 久久久久久综合一区中文字幕 | 久久久久99精品成人片试看 | 2020最新久久久视精品爱| 一日本道伊人久久综合影| 久久久无码精品亚洲日韩按摩 | 久久综合给合久久狠狠狠97色69| 久久se精品一区二区| 久久天天躁狠狠躁夜夜2020一| 亚洲综合久久综合激情久久| 狠狠色噜噜色狠狠狠综合久久| 99久久国产综合精品网成人影院| 少妇高潮惨叫久久久久久| 日本精品久久久久久久久免费| 久久精品国产亚洲一区二区| 97精品国产97久久久久久免费 | 91久久精品视频| 国产精品99久久精品| 欧美日韩久久中文字幕| 久久人人爽人人精品视频| 久久精品国产亚洲av麻豆色欲| 久久久久国产一区二区三区| 色综合久久88色综合天天 | 国产亚洲综合久久系列| 伊人久久大香线蕉AV色婷婷色| 久久综合五月丁香久久激情| 国产精品99久久不卡| 国产精品女同一区二区久久| 国产成人精品久久综合 | 青青草原综合久久大伊人导航| 久久国产成人精品麻豆| 精品综合久久久久久888蜜芽| 久久亚洲春色中文字幕久久久| 无码国内精品久久综合88| 亚洲色欲久久久久综合网| 久久综合色老色|