第十一个工具类: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;