共享内存创建及哈希索引

构建一个共享内存的资源池,用于后续的使用
创建共享内存资源池的思路:
1、申请的内存由表头数据结构(相关统计信息)和节点数据结构组成
2、内存节点之间利用索引位置串联而成一个类似双向链表的数据结构
3、每次插入节点数据时,都从可用的头节点位置获取可用节点(freeheadpos),并从可用节点链表中去除节点数据
4、而当删除节点数据时,则将其添加到可用链表的头节点位置处
5、利用自定义索引字段来构建hash值,每个hash值对应一个map,用于保存具有同样hash值的节点。查找节点时,就先利用hash找到指定的map,再遍历map确认具体的节点
6、每个节点的数据结构利用“char node[1]”中的node来找到节点数据的指针位置,从而可读取数据值

 

// 每个节点的数据结构
struct MEMNODE
{
    int prepos; // 前一个节点的位置索引,第一个指向0
    int nextpos; // 后一个节点的位置索引,最后一个指向0
    bool isfree; //是否被使用了
    char node[1]; // 每个节点所存储数据的起始位置,node为起始位置的首地址
};
// 共享内存的表头信息
struct MEMHEAD
{
    int freeheadpos; //空闲节点的头节点索引位置,用于后续从这个地方分配节点,且为连续的分配,表示第几个节点
    int freecnt;     //可用的空闲节点数目
    int allcnt;      // 所有的节点数目
    int hashsize;    // hash桶的大小
};
// NODE为所储存的数据结构,所以每个MEMNODE的大小为:(sizeof(MEMNODE) - 1 + sizeof(NODE))
template<typename INDEX, typename NODE>
class Shm_Mapper
{
       vector<map<INDEX, int> > Index_mapper_List;    // 每个map存储一个hashvalue所对应的所有节点的索引及在内存中的位置。
       MEMHEAD *pMemHead;
       void *pMapbeg;
       bool isopen;
       int ipckey;
};

// 随着节点的申请和释放,将导致整个freeheadpos链表不再是连续的
// 通过freeheadpos变量可以找到第一个节点
int AllocNode(Shm_Mapper<INDEX, NODE>::MEMNODE* &memnode)
{
    memnode = NULL;
    
    if (pMemHead->freecnt <= 0)
    {
        return -1;
    }

    --(pMemHead->freecnt);

    memnode = Pos2Node(pMemHead->freeheadpos);
    pMemHead->freeheadpos = memnode->nextpos;

    //设置新的空闲首节点prepos为0
    if (pMemHead->freeheadpos > 0)
    {
        MEMNODE* newhead = Pos2Node(pMemHead->freeheadpos);
        newhead->prepos = 0;
    }

    //将新获取的节点清空隔离
    memnode->nextpos = 0;
    memnode->prepos = 0;
    memnode->isfree = false;

    return 0;
}

//将节点资源变为可用节点
FreeNode(Shm_Mapper<INDEX, NODE>::MEMNODE* memnode)
{
    int curpos = Node2Pos(memnode);
    if (pMemHead->freeheadpos > 0)
    {
        MEMNODE* oldhead = Pos2Node(pMemHead->freeheadpos);
        oldhead->prepos = curpos;
    }

    memnode->nextpos = pMemHead->freeheadpos;
    memnode->prepos = 0;
    memnode->isfree = true;
    memset(memnode->node, 0, sizeof(NODE));
    pMemHead->freeheadpos = curpos;
    ++(pMemHead->freecnt);

    return 0;
}

//通过索引来查询到指定的节点,只需要先利用index得到hashvalue,再将hashvalue作为索引由Index_mapper_List得到相应的map,最后利用index查找map得到节点的索引值,即可得到节点。
template<typename INDEX, typename NODE>
int Shm_Mapper<INDEX, NODE>::Open(int ipckey, int nodecnt, int hashsize)
{
    ipckey = ipckey;
    int memsize = sizeof(MEMHEAD) + MEMNODESIZE * nodecnt;
    int iShmID = 0;
    bool isfirst = false;

    if (ipckey == 0)
    {
        // 分配普通的内存
        pMapbeg = new char[memsize];

        if (NULL == pMapbeg)
        {
            return -1;
        }
        memset(pMapbeg, 0, memsize);
        pMemHead = (MEMHEAD*)pMapbeg; //得到表头的指针
    }else{
        //试图创建
        if ((iShmID = shmget(ipckey, memsize, IPC_CREAT | IPC_EXCL | 0666)) < 0)
        {
            //若已经存在,则试图连接
            if ((iShmID = shmget(ipckey, memsize, 0666)) < 0)
            {
                return -1;
            }
        }
        else
        {
            isfirst = true;
        }

        pMapbeg = shmat(iShmID, (const void*)NULL, 0);
        pMemHead = (MEMHEAD*)pMapbeg;
    }

    return InitMem(isfirst, nodecnt, hashsize);
}

//初始化共享内存的信息
template<typename INDEX, typename NODE>
int Shm_Mapper<INDEX, NODE>::InitMem(bool isfirst, int nodecnt, int hashsize)
{
    //首次创建,将贡献内存节点块全部放入空闲链表
    if (isfirst)
    {
        pMemHead->freeheadpos = 1;
        pMemHead->freecnt = nodecnt;
        pMemHead->allcnt = nodecnt;
        pMemHead->hashsize = hashsize;

        for (int i = 0; i < pMemHead->hashsize; ++i)
        {
            Index_mapper_List.push_back(map<INDEX, int>());
        }
                        
        for (int i = 1; i <= pMemHead->allcnt; ++i)
        {
            MEMNODE* memnode = Pos2Node(i);
            memnode->isfree = true;
            memnode->prepos = i - 1;
            //尾节点 nextpos置为0
            if (i == nodecnt)
            {
                memnode->nextpos = 0;
            }
            else
            {
                memnode->nextpos = i + 1;
            }
            memset(memnode->node, 0, sizeof(NODE));
        }
    }
    else//非首次创建则读取共享内存索引
    {
        for (int i = 0; i < pMemHead->hashsize; ++i)
        {
            Index_mapper_List.push_back(map<INDEX, int>());
        }
        for (int i = 1; i <= pMemHead->allcnt; ++i)
        {
            MEMNODE *memnode = Pos2Node(i);
            //处理头节点
            if (0 == memnode->prepos)
            {
                //空闲节点头节点
                if (memnode->isfree == true)
                {
                    if (pMemHead->freeheadpos != i)
                    {
                        return -1;   
                    }
                }
                else
                {
                    if (InitMapList(memnode, i) < 0)
                    {
                        return -1;
                    }
                }
            }
        }
    }

    isOpen = true;
    return 0;
}


//将memnode的索引及其节点的位置保存
template<typename INDEX, typename NODE>
int Shm_Mapper<INDEX, NODE>::InitMapList(const MEMNODE* memnode, const int& curpos)
{
    if (memnode->prepos != 0 || memnode->isfree == true)
    {
        return -1;
    }

    INDEX index;
    int hashvalue;
    Node2Index(*((NODE*)(memnode->node)), index);
    Index2Hash(index, hashvalue);

    if (hashvalue >= pMemHead->hashsize)
    {
        return -1;
    }

    map<INDEX, int>& index_mapper = Index_mapper_List[hashvalue];

    typename map<INDEX, int>::iterator iter = index_mapper.find(index);

    if (iter != index_mapper.end())
    {
        return -1;
    }
    index_mapper.insert(typename map<INDEX, int>::value_type(index, curpos));

    return 0;
}



template<typename INDEX, typename NODE>
int Shm_Mapper<INDEX, NODE>::InsertNode(const NODE& node, Shm_Mapper<INDEX, NODE>::MEMNODE* &memnode)
{
    memnode = NULL;
    
    INDEX index;
    int hashvalue;
    Node2Index(node, index);
    Index2Hash(index, hashvalue);
    
    if (hashvalue >= pMemHead->hashsize)
    {
        return -1;
    }
    
    map<INDEX, int>& index_mapper = Index_mapper_List[hashvalue];

    typename map<INDEX, int>::iterator iter = index_mapper.find(index);

    //检查索引不存在,则创建
    if (iter == index_mapper.end())
    {
        if (AllocNode(memnode) < 0)
        {
            return -1;
        }

        memcpy(memnode->node, &node, sizeof(NODE));

        int curpos = Node2Pos(memnode);
        index_mapper.insert(typename map<INDEX, int>::value_type(index, curpos));
    }
    //检查索引存在则覆盖
    else
    {
        int i = iter->second;
        if (i > 0)
        {
            memnode = Pos2Node(i);
            memcpy(memnode->node, &node, sizeof(NODE));
        }
        //如果索引下面没有挂载数据,则重新申请
        else
        {
            if (AllocNode(memnode) < 0)
            {
                return -1;
            }
            
            memcpy(memnode->node, &node, sizeof(NODE));
            
            int curpos = Node2Pos(memnode);
            iter->second = curpos;
        }
    }
    return 0;
}

template<typename INDEX, typename NODE>
int Shm_Mapper<INDEX, NODE>::QuerybyIndex(const INDEX &index, Shm_Mapper<INDEX, NODE>::MEMNODE* &memnode)
{
    memnode = NULL;
    int hashvalue;
    Index2Hash(index, hashvalue);
    
    if (hashvalue >= pMemHead->hashsize)
    {
        return -1;
    }

    map<INDEX, int>& index_mapper = Index_mapper_List[hashvalue];

    typename map<INDEX, int>::iterator iter = index_mapper.find(index);

    if (iter == index_mapper.end())
    {
        return 0;
    }

    int i = iter->second;
    if (i == 0)
    {
        return -1;
    }
    else
    {
        memnode = Pos2Node(i);
    }

    return 0;
}

template<typename INDEX, typename NODE>
int Shm_Mapper<INDEX, NODE>::DeleteNode(Shm_Mapper<INDEX, NODE>::MEMNODE* memnode)
{
    if (memnode->isfree == true)
    {
        return 0;
    }

    int curpos = Node2Pos(memnode);

    //为索引首字段
    if (memnode->prepos == 0)
    {
        INDEX index;
        int hashvalue;
        Node2Index(*((NODE *)memnode->node), index);
        Index2Hash(index, hashvalue);

        if (hashvalue >= pMemHead->hashsize)
        {
            return -1;
        }

        map<INDEX, int>& index_mapper = Index_mapper_List[hashvalue];

        typename map<INDEX, int>::iterator iter = index_mapper.find(index);

        if (iter == index_mapper.end())
        {
            return -1;
        }

        if (curpos != iter->second)
        {
            return  -1;
        }

        //设置新的空闲首节点prepos为0
        if (memnode->nextpos > 0)
        {
            MEMNODE* newhead = Pos2Node(memnode->nextpos);
            newhead->prepos = 0;
            iter->second = memnode->nextpos;
        }
        else//只有一个节点直接删掉索引
        {
            index_mapper.erase(iter);
        }
    }
    else
    {
        return  -1;
    }

    //将新获取的节点清空隔离
    memnode->nextpos = 0;
    memnode->prepos = 0;
    FreeNode(memnode);
    return 0;
}

struct stInfo
{
    char[30] str;
    string data;
}

typedef char[30] stIndex;

void Node2Index(const stInfo &node, stIndex &index)
{
    index = node.str;
}

void Index2Hash(const stIndex &index, int &hashvalue)
{
    hashvalue = 0;
    int len = index.strlen();
    for (int i = 0; i < len; ++i)
    {
        hashvalue = ((unsigned char)index[i] + hashvalue) % pMemHead->hashsize;
    }
}

template<typename INDEX, typename NODE>
typename Shm_Mapper<INDEX, NODE>::MEMNODE *Shm_Mapper<INDEX, NODE>::Pos2Node(const int& pos)
{
    if (pos <= 0)
    {
        return (MEMNODE*)NULL;
    }
    else
    {
        return (MEMNODE*)((char *)_pMapbeg + sizeof(MEMHEAD) + MEMNODESIZE * (pos - 1));
    }
}

template<typename INDEX, typename NODE>
int Shm_Mapper<INDEX, NODE>::Node2Pos(const Shm_Mapper<INDEX, NODE>::MEMNODE* memnode)
{
    if (memnode == NULL)
    {
        return 0;
    }
    else
    {
        return (int)(((char*)memnode - (char*)_pMapbeg - sizeof(MEMHEAD))/MEMNODESIZE + 1);
    }

}
View Code

 

转载于:https://www.cnblogs.com/share-ideas/p/10957284.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值