工具类库系列(十一)-ObjectMap

时间:2021-11-01 19:00:49

第十一个工具类:ObjectMap


ObjectMap 是一个上篇提到的 objectid64 的一个id<->id映射关系表,由map实现


该类用于需求中时常会出现的 1对1  或者 1对多 映射关系,

比如:

1对1:一个网络链接对象 对应 一个玩家数据对象, 一个玩家数据对象 也对应一个 网络链接对象

1对多:一个玩家对象 对应 一个游戏公会对象


同时:

1、继承boost::noncopyable,禁止ObjectMap对象间拷贝赋值

2、ObjectMap加了锁,确保操作是线程安全了

3、实现了当一个线程在对ObjectMap进行迭代,其他线程在对ObjectMap进行添加/删除,确保迭代不失效


如何实现保证迭代不失效:

ObjectMap中保存了迭代时当前的迭代器std::map::iterator对象

当做删除操作时,先检查下要删除的这个对象是否就是当前正在遍历的那个对象

是的话,则保存的迭代器后移,再删除


提供的主要接口:

1、增加一个id<->id的映射关系:void AddObject(objectid64 key, objectid64 value);

2、查找一个id<->id映射关系(没找到返回NULL_ID):objectid64 FindObject(objectid64 key);

3、判断一个id<->id映射关系是否存在:bool IsExistsObject(objectid64 key);

4、删除一个id<->id映射关系:void FreeObject(objectid64 key);

5、获取id<->id映射关系的数量:unsigned int GetSize();

6、迭代:objectid64 BeginObject();  objectid64 NextObject();


上代码:

ObjectMap.h

#ifndef __ObjectMap_h__
#define __ObjectMap_h__

#include <boost/noncopyable.hpp>
#include <map>

#include "ToolDefine.h"

namespace common{
namespace tool{

// 纯uint64的键值对池
// 主要用于id对id的索引
class ObjectMap : private boost::noncopyable
{
public:
ObjectMap();
~ObjectMap();

// 使用一个空闲结点
void AddObject(objectid64 key, objectid64 value);

// 随机一个结点(分配第一个结点,空列表返回空)
objectid64 RandObject();

// 查找一个结点(没找到返回空)
objectid64 FindObject(objectid64 key);
bool IsExistsObject(objectid64 key);

// 释放一个结点
void FreeObject(objectid64 key);

// 获取对象个数
unsigned int GetSize();

// 迭代
objectid64 BeginObject();
objectid64 NextObject();

private:
rw_mutex m_object_list_lock;

typedef std::map<objectid64, objectid64> MapType;
typedef std::map<objectid64, objectid64>::iterator MapTypeIterator;

MapType m_object_list;
MapTypeIterator m_object_it;
};

}
}

#endif

ObjectMap.cpp

#include "ObjectMap.h"

namespace common{
namespace tool{

ObjectMap::ObjectMap()
{
write_lock lock(m_object_list_lock);

m_object_list.clear();
m_object_it = m_object_list.begin();
}

ObjectMap::~ObjectMap()
{
write_lock lock(m_object_list_lock);

m_object_list.clear();
m_object_it = m_object_list.begin();
}

void ObjectMap::AddObject(objectid64 key, objectid64 value)
{
write_lock lock(m_object_list_lock);

m_object_list[key] = value;
}

objectid64 ObjectMap::RandObject()
{
read_lock lock(m_object_list_lock);

MapTypeIterator it = m_object_list.begin();
if (it != m_object_list.end())
{
return it->second;
}
else
{
return NULL_ID;
}
}

objectid64 ObjectMap::FindObject(objectid64 key)
{
read_lock lock(m_object_list_lock);

MapTypeIterator it = m_object_list.find(key);
if (it != m_object_list.end())
{
return it->second;
}
else
{
return NULL_ID;
}
}

bool ObjectMap::IsExistsObject(objectid64 key)
{
read_lock lock(m_object_list_lock);

MapTypeIterator it = m_object_list.find(key);
if (it != m_object_list.end())
{
return true;
}
else
{
return false;
}
}

void ObjectMap::FreeObject(objectid64 key)
{
write_lock lock(m_object_list_lock);

MapTypeIterator it = m_object_list.find(key);
if (it != m_object_list.end())
{
// 删除结点
if (m_object_it == it)
{
m_object_list.erase(m_object_it++);
}
else
{
m_object_list.erase(it);
}
}
}

unsigned int ObjectMap::GetSize()
{
read_lock lock(m_object_list_lock);

return m_object_list.size();
}

objectid64 ObjectMap::BeginObject()
{
write_lock lock(m_object_list_lock);

m_object_it = m_object_list.begin();
if (m_object_it != m_object_list.end())
{
return (m_object_it++)->second;
}
else
{
return NULL_ID;
}
}

objectid64 ObjectMap::NextObject()
{
write_lock lock(m_object_list_lock);

if (m_object_it != m_object_list.end())
{
return (m_object_it++)->second;
}
else
{
return NULL_ID;
}
}

}
}


其中ToolDefine.h增加了定义读写锁

//读写锁
typedef boost::shared_mutex rw_mutex;
typedef boost::shared_lock<rw_mutex> read_lock;
typedef boost::unique_lock<rw_mutex> write_lock;