linux下的简单共享内存map实现

由于一些需求需要,简单实现了一个共享内存map。

 

#ifndef MKEYINTSHMMAP_HPP_
#define  MKEYINTSHMMAP_HPP_

#include 
< sys / ipc.h >
#include 
< sys / shm.h >

/**
 * 适合小数据量,int 索引
 * 数据量越多效率相对降低.
 * 每次插入,删除都会重建索引
 * 查找相对快速,二分数组查找.
 * 适合于load数据到内存的查询修改操作.对于频繁增加减少的不适合
 * 
 * 没有锁操作,如果多进程操作,自己加锁
 * 
 * T 必须是不含有指针的固定大小可存入结构体
 * 
 
*/

 
 
template
< class  T >
class  MKeyIntShmMap
{
public:
    MKeyIntShmMap(
int t_shmkey,int t_max_size)
    
{
        max_size 
= t_max_size;
        sizePtr 
= NULL;
        keyPtr 
= NULL;
        elementPtr 
= NULL;
        
int shmid;
        shmid
=shmget(t_shmkey,sizeof(int)+(sizeof(int)*3)*t_max_size+t_max_size*sizeof(T),IPC_CREAT|0666);
        
if(shmid<=0)
        
{
            fprintf(stderr,
" shm new exception: file=[%s] line=[%d] code=[%d] ",__FILE__,__LINE__,MEXP_NEW);
            
throw MEXP_NEW;
        }

        
int addr = (int)shmat(shmid, 00);
        
if(addr<=0)
        
{
            fprintf(stderr,
" shm mat exception: file=[%s] line=[%d] code=[%d] ",__FILE__,__LINE__,MEXP_NEW);
            
throw MEXP_NEW;
        }

        shm_addr 
= (char *)addr;
        
        
//共享内存第一段int 存个数
        sizePtr = (int *)shm_addr;
        
//第二位存最小空闲块
        minfreePtr = (int *)(shm_addr+sizeof(int));
        
//共享内存第二段,存 key 列表
        keyPtr = (int *)(shm_addr+sizeof(int)*2);
        
//共享内存第三段,存 块占用标记
        indexPtr = (int *)(shm_addr+sizeof(int)*2+sizeof(int)*max_size);
        
//存内存使用标记
        flagPtr = (int *)(shm_addr+sizeof(int)*2+sizeof(int)*max_size+sizeof(int)*max_size);
        
//共享内存第四段,数据区域
        elementPtr = (T *)(shm_addr+sizeof(int)*2+sizeof(int)*max_size+sizeof(int)*max_size+sizeof(int)*max_size);
        
        
//第一次创建
        struct shmid_ds shmid_st;
        shmctl(shmid, IPC_STAT, 
&shmid_st);
        
if (shmid_st.shm_cpid == getpid())
        
{
            
*sizePtr = 0;
            
*minfreePtr = 0;
            
for(int i=0;i<max_size;i++)
            
{
                flagPtr[i] 
= 0;
            }

        }

        
    }

    
    
~MKeyIntShmMap()
    
{
    }

    
    T
* add(int key,const T& obj)
    
{
        
if((*sizePtr)>=max_size)
        
{
            
return NULL;
        }

        
int pos = 0;
        
int flag = findPos(key,pos);
        
if(flag)
        
{
            
//flagPtr[indexPtr[pos]] = 0;
            elementPtr[indexPtr[pos]] = obj;
        }

        
else
        
{
            
for(int i=(*sizePtr);i>pos;i--)
            
{
                keyPtr[i] 
= keyPtr[i-1];
                indexPtr[i] 
= indexPtr[i-1];
            }

            
int tpos = -1;
            
for(int i=(*minfreePtr);i<max_size;i++)
            
{
                
if(flagPtr[i]==0)
                
{
                    tpos 
= i;
                    
break;
                }

            }

            flagPtr[tpos] 
= 1;
            (
*minfreePtr) = tpos+1;
            keyPtr[pos] 
= key;
            indexPtr[pos] 
= tpos;
            elementPtr[tpos] 
= obj;
            (
*sizePtr)++;
        }

        
return &elementPtr[indexPtr[pos]];
    }

    
    
void del(int key)
    
{
        
int pos = 0;
        
int flag = findPos(key,pos);
        
if(flag)
        
{
            flagPtr[indexPtr[pos]] 
= 0;
            
if((*minfreePtr)>indexPtr[pos])
            
{
                (
*minfreePtr) = indexPtr[pos];
            }

            
for(int i=pos+1;i<(*sizePtr);i++)
            
{
                keyPtr[i
-1= keyPtr[i];
                indexPtr[i
-1= indexPtr[i];
            }

            (
*sizePtr)--;
        }

    }

    
    T
& operator[](int key)
    
{
        
if((*sizePtr)>=max_size)
        
{
            fprintf(stderr,
" shm full exception: file=[%s] line=[%d] code=[%d] ",__FILE__,__LINE__,MEXP_NEW);
            
throw MEXP_NEW;
        }

        
int pos = 0;
        
int flag = findPos(key,pos);
        
if(flag)
        
{
            
return elementPtr[indexPtr[pos]];
        }

        
else
        
{
            
for(int i=(*sizePtr);i>pos;i--)
            
{
                keyPtr[i] 
= keyPtr[i-1];
                indexPtr[i] 
= indexPtr[i-1];
            }

            
int tpos = -1;
            
for(int i=(*minfreePtr);i<max_size;i++)
            
{
                
if(flagPtr[i]==0)
                
{
                    tpos 
= i;
                    
break;
                }

            }

            flagPtr[tpos] 
= 1;
            (
*minfreePtr) = tpos+1;
            keyPtr[pos] 
= key;
            indexPtr[pos] 
= tpos;
            T obj;
            elementPtr[tpos] 
= obj;
            (
*sizePtr)++;
            
return elementPtr[indexPtr[pos]];
        }

    }

    
    T
* find(int key)
    
{
        
int pos = 0;
        
int flag = findPos(key,pos);
        
if(flag)
        
{
            
return &elementPtr[indexPtr[pos]];
        }

        
else
        
{
            
return NULL;
        }

    }

    
int getSize()
    
{
        
return (*sizePtr);
    }

    
    
int getKey(int pos)
    
{
        
return keyPtr[pos];
    }

    
    T
* get(int pos)
    
{
        
return &elementPtr[indexPtr[pos]];
    }

    
    
void clear()
    
{
        
*sizePtr = 0;
        
for(int i=0;i<max_size;i++)
        
{
            flagPtr[i] 
= 0;
        }

        (
*minfreePtr) = 0;
    }

protected:

private:
    
//找到key所在的位置
    
//找到key,返回1,pos指向所在位置
    
//找不到key,返回0,pos指向所应该插入位置
    int findPos(int key,int &pos)
    
{
        
if((*sizePtr)==0)
        
{
            pos 
= 0;
            
return 0;
        }

        
int p0 = 0;
        
int p2 = (*sizePtr)-1;
        
int p1 = (p0+p2)/2;
        
while(true)
        
{
            
int cmp = 0;
            
if(key>keyPtr[p1])
            
{
                cmp 
= 1;
            }

            
else if(key<keyPtr[p1])
            
{
                cmp 
= -1;
            }

            
else
            
{
                cmp 
= 0;
            }

            
if(cmp>0)
            
{
                
if(p2-p1>1)
                
{
                    p0 
= p1;
                    p1 
= (p0+p2)/2;
                }

                
else
                
{
                    
if(key>keyPtr[p2])
                    
{
                        pos 
= p2+1;
                        
return 0;
                    }

                    
else if(key<keyPtr[p2])
                    
{
                        pos 
= p1+1;
                        
return 0;
                    }

                    
else
                    
{
                        pos 
= p2;
                        
return 1;
                    }

                }

            }

            
else if(cmp<0)
            
{
                
if(p1-p0>1)
                
{
                    p2 
= p1;
                    p1 
= (p0+p2)/2;
                }

                
else
                
{
                    
if(key<keyPtr[p0])
                    
{
                        pos 
= p0;
                        
return 0;
                    }

                    
else if(key>keyPtr[p0])
                    
{
                        pos 
= p0+1;
                        
return 0;
                    }

                    
else
                    
{
                        pos 
= p0;
                        
return 1;
                    }

                }

            }

            
else
            
{
                pos 
= p1;
                
return 1;
            }

        }

    }
    
    
char * shm_addr;
    
int max_size;
    
int * minfreePtr;
    
int * sizePtr;
    
int * keyPtr;
    
int * flagPtr;
    
int * indexPtr;
    T
* elementPtr;    //数据中不含NULL指针
}
;

/*
 * 没有测试过,可能含有错误,因为map操作,最好在应用层考虑加解锁,所以,不建议使用
template<class T>
class MKeyIntShmSafeMap
{
public:
    MKeyIntShmSafeMap(int t_shmkey,int t_semkey,int t_max_size)
    {
        int sid;
        sid=semget(t_semkey,1,IPC_CREAT|0666);
        if(sid<=0)
        {
            fprintf(stderr," sem new exception: file=[%s] line=[%d] code=[%d] ",__FILE__,__LINE__,MEXP_NEW);
            throw MEXP_NEW;
        }
        semun arg;
        arg.val = 1;
        if (semctl(sid, 0, SETVAL, arg)==-1)
        {
            fprintf(stderr," sem ctl exception: file=[%s] line=[%d] code=[%d] ",__FILE__,__LINE__,MEXP_NEW);
            throw MEXP_NEW;
        }
        
        semid = sid;
        
        lock();
        max_size = t_max_size;
        sizePtr = NULL;
        keyPtr = NULL;
        elementPtr = NULL;
        int shmid;
        shmid=shmget(t_shmkey,sizeof(int)+(sizeof(int)*3)*t_max_size+t_max_size*sizeof(T),IPC_CREAT|0666);
        if(shmid<=0)
        {
            fprintf(stderr," shm new exception: file=[%s] line=[%d] code=[%d] ",__FILE__,__LINE__,MEXP_NEW);
            unlock();
            throw MEXP_NEW;
        }
        int addr = (int)shmat(shmid, 0, 0);
        if(addr<=0)
        {
            fprintf(stderr," shm mat exception: file=[%s] line=[%d] code=[%d] ",__FILE__,__LINE__,MEXP_NEW);
            unlock();
            throw MEXP_NEW;
        }
        shm_addr = (char *)addr;
        
        //共享内存第一段int 存个数
        sizePtr = (int *)shm_addr;
        //第二位存最小空闲块
        minfreePtr = (int *)(shm_addr+sizeof(int));
        //共享内存第二段,存 key 列表
        keyPtr = (int *)(shm_addr+sizeof(int)*2);
        //共享内存第三段,存 块占用标记
        indexPtr = (int *)(shm_addr+sizeof(int)*2+sizeof(int)*max_size);
        //存内存使用标记
        flagPtr = (int *)(shm_addr+sizeof(int)*2+sizeof(int)*max_size+sizeof(int)*max_size);
        //共享内存第四段,数据区域
        elementPtr = (T *)(shm_addr+sizeof(int)*2+sizeof(int)*max_size+sizeof(int)*max_size+sizeof(int)*max_size);
        
        //第一次创建
        struct shmid_ds shmid_st;
        shmctl(shmid, IPC_STAT, &shmid_st);
        if (shmid_st.shm_cpid == getpid())
        {
            *sizePtr = 0;
            *minfreePtr = 0;
            for(int i=0;i<max_size;i++)
            {
                flagPtr[i] = 0;
            }
        }
        unlock();
    }
    
    ~MKeyIntShmMap()
    {
    }
    
    int add(int key,const T& obj)
    {
        lock();
        if((*sizePtr)>=max_size)
        {
            unlock();
            return -1;
        }
        int pos = 0;
        int flag = findPos(key,pos);
        if(flag)
        {
            //flagPtr[indexPtr[pos]] = 0;
            elementPtr[indexPtr[pos]] = obj;
        }
        else
        {
            for(int i=(*sizePtr);i>pos;i--)
            {
                keyPtr[i] = keyPtr[i-1];
                indexPtr[i] = indexPtr[i-1];
            }
            int tpos = -1;
            for(int i=(*minfreePtr);i<max_size;i++)
            {
                if(flagPtr[i]==0)
                {
                    tpos = i;
                    break;
                }
            }
            flagPtr[tpos] = 1;
            (*minfreePtr) = tpos+1;
            keyPtr[pos] = key;
            indexPtr[pos] = tpos;
            elementPtr[tpos] = obj;
            (*sizePtr)++;
        }
        unlock();
        return 0;
    }
    
    void del(int key)
    {
        lock();
        int pos = 0;
        int flag = findPos(key,pos);
        if(flag)
        {
            flagPtr[indexPtr[pos]] = 0;
            if((*minfreePtr)>indexPtr[pos])
            {
                (*minfreePtr) = indexPtr[pos];
            }
            for(int i=pos+1;i<(*sizePtr);i++)
            {
                keyPtr[i-1] = keyPtr[i];
                indexPtr[i-1] = indexPtr[i];
            }
            (*sizePtr)--;
        }
        unlock();
    }
    
    int find(int key,T & obj)
    {
        lock();
        int pos = 0;
        int flag = findPos(key,pos);
        if(flag)
        {
            obj = elementPtr[indexPtr[pos]];
            unlock();
            return 0;
        }
        else
        {
            unlock();
            return -1;
        }
    }
    int getSize()
    {
        return (*sizePtr);
    }
    
    int getKey(int pos)
    {
        return keyPtr[pos];
    }
    
    int get(int pos,T &obj)
    {
        obj = elementPtr[indexPtr[pos]];
    }
    
    void clear()
    {
        lock();
        *sizePtr = 0;
        for(int i=0;i<max_size;i++)
        {
            flagPtr[i] = 0;
        }
        (*minfreePtr) = 0;
        unlock();
    }
protected:

private:
    //找到key所在的位置
    //找到key,返回1,pos指向所在位置
    //找不到key,返回0,pos指向所应该插入位置
    int findPos(int key,int &pos)
    {
        if((*sizePtr)==0)
        {
            pos = 0;
            return 0;
        }
        int p0 = 0;
        int p2 = (*sizePtr)-1;
        int p1 = (p0+p2)/2;
        while(true)
        {
            int cmp = 0;
            if(key>keyPtr[p1])
            {
                cmp = 1;
            }
            else if(key<keyPtr[p1])
            {
                cmp = -1;
            }
            else
            {
                cmp = 0;
            }
            if(cmp>0)
            {
                if(p2-p1>1)
                {
                    p0 = p1;
                    p1 = (p0+p2)/2;
                }
                else
                {
                    if(key>keyPtr[p2])
                    {
                        pos = p2+1;
                        return 0;
                    }
                    else if(key<keyPtr[p2])
                    {
                        pos = p1+1;
                        return 0;
                    }
                    else
                    {
                        pos = p2;
                        return 1;
                    }
                }
            }
            else if(cmp<0)
            {
                if(p1-p0>1)
                {
                    p2 = p1;
                    p1 = (p0+p2)/2;
                }
                else
                {
                    if(key<keyPtr[p0])
                    {
                        pos = p0;
                        return 0;
                    }
                    else if(key>keyPtr[p0])
                    {
                        pos = p0+1;
                        return 0;
                    }
                    else
                    {
                        pos = p0;
                        return 1;
                    }
                }
            }
            else
            {
                pos = p1;
                return 1;
            }
        }
    }    
    
    void lock()
    {
        //加锁
        struct sembuf op[1] = {{0, -1, 0}};
        if (semop (sid, &op[0], 1) == -1)
        {
            fprintf(stderr," sem lock exception: file=[%s] line=[%d] code=[%d] ",__FILE__,__LINE__,MEXP_NEW);
            throw MEXP_NEW;
        }
    }
    void unlock()
    {
        //解锁
        struct sembuf op[1] = {{0, 1, 0}};
        if (semop (sid, &op[0], 1) == -1)
        {
            fprintf(stderr," sem unlock exception: file=[%s] line=[%d] code=[%d] ",__FILE__,__LINE__,MEXP_NEW);
            throw MEXP_NEW;
        }
    }
    int semid;
    char * shm_addr;
    int max_size;
    int * minfreePtr;
    int * sizePtr;
    int * keyPtr;
    int * flagPtr;
    int * indexPtr;
    T* elementPtr;    //数据中不含NULL指针
};
*/

#endif  /*MKEYINTSHMMAP_HPP_*/

 使用实例

 

#include  " MTest.h "

typedef MKeyIntShmMap
< int >  MyMKeyIntShmMap;

typedef 
struct
{
    
int id;
    
char name[123];
}
MyStruct;

typedef MKeyIntShmMap
< MyStruct >  StructMKeyIntShmMap;

int  main( int  agrc, char   *  argv[])
{
    MyMKeyIntShmMap myMap(
99123,100);
    
    
if(agrc==2)
    
{
        myMap.del(atoi(argv[
1]));
    }

    
    
if(agrc==4)
    
{
        myMap.clear();
    }

    
    
if(agrc==3)
    
{
        myMap[atoi(argv[
1])] = atoi(argv[2]);
    }

    printf(
"map size = %d ",myMap.getSize());
    myMap[
1= 123;
    printf(
"map size = %d ",myMap.getSize());
    myMap[
128= 212;
    printf(
"map size = %d ",myMap.getSize());
    myMap[
123= 22;
    printf(
"map size = %d ",myMap.getSize());
    
    printf(
"key=value ");
    
for(int i=0;i<myMap.getSize();i++)
    
{
        printf(
" %d=%d ",myMap.getKey(i),*myMap.get(i));
    }

    
    StructMKeyIntShmMap test(
99124,5);
    
for(int i=0;i<8;i++)
    
{
        MyStruct cc;
        cc.id 
= 123+i;
        snprintf(cc.name,
sizeof(cc.name)-1,"hello%d",i);
        test.add(i
*2,cc);
    }

    
for(int i=0;i<test.getSize();i++)
    
{
        printf(
" %d=%d %s ",test.getKey(i),test.get(i)->id,test.get(i)->name);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值