以STL::map实现引用表的一种方式

一直受惠于EasyDarWin开源项目,因此把自己的一些想法分享出来,希望能够帮助到其他人。

之前在推流测试中出现引用表异常的情况,经跟踪发现是内部封装的哈希表的hash函数对于传入的字符串无法得到一个唯一的key,下面是具体的hash函数

UInt32  OSRefTableUtils::HashString(StrPtrLen* inString)
{
    Assert(inString != NULL);
    Assert(inString->Ptr != NULL);
    Assert(inString->Len > 0);
    if (inString == NULL || inString->Len == 0 || inString->Ptr == NULL)
        return 0;
    
    //make sure to convert to unsigned here, as there may be binary
    //data in this string
    UInt8* theData = (UInt8*)inString->Ptr;
    
    //divide by 4 and take the characters at quarter points in the string,
    //use those as the basis for the hash value
    UInt32 quarterLen = inString->Len >> 2;
    return (inString->Len * (theData[0] + theData[quarterLen] +
            theData[quarterLen * 2] + theData[quarterLen * 3] +
            theData[inString->Len - 1]));
}
其实对于hash函数本没没有什么错误,但我们的应用场景是对于一个传入的不同字符串参数,总能够可以进行快速的查询、插入等,而hash表从本质上来说是不可能避免冲突的,因此在此考虑使用在map的基础上来设计引用表。

在引用表的设计中参考了原Darwin的设计,并保持接口几乎一致,这样就比较便于修改。其中关键点有两个:1是对map的互斥和同步操作,在数据结构的设计上加入了互斥操作,可以放心的去调用。2是当释放对象时,该对象的引用必须为0,否则会产生不可想象的错误。下面看一下具体实现

#include "OSCond.h"
#include "OSHeaders.h"
class OSRefTableEx
{
public:
	class OSRefEx
	{
	private:
		void *mp_Object;//引用的对象或其余数据
		int m_Count;//当前引用对象计数,只有为0时才允许对象销毁
		OSCond  m_Cond;//to block threads waiting for this ref.
	public:
		OSRefEx():mp_Object(NULL),m_Count(0){}
		OSRefEx(void * pobject):mp_Object(pobject),m_Count(0){}
	public:
		void *GetObjectPtr(){return mp_Object;}
		int GetRefNum(){return m_Count;}
		OSCond *GetCondPtr(){return &m_Cond;}
		void AddRef(int num){m_Count+=num;}
	};
private:
	map<string,OSRefTableEx::OSRefEx*> m_Map;//以string为key,以OSRefEx为value
	OSMutex         m_Mutex;//提供对map的互斥操作
public:
	OSRefEx *    Resolve(string keystring);//引用对象
	OS_Error     Release(string keystring);//释放引用
	OS_Error     Register(string keystring,void* pobject);//加入到map中
	OS_Error     UnRegister(string keystring);//从map中移除

	OS_Error TryUnRegister(string keystring);//尝试移除,如果引用为0,则移除并返回true,否则返回false
public:
	int GetEleNumInMap(){return m_Map.size();}//获得map中的元素个数
	OSMutex *GetMutex(){return &m_Mutex;}//给外面提供互斥接口
	map<string,OSRefTableEx::OSRefEx*> *GetMap(){return &m_Map;}
};
可以看到,引用表封装的map的key和value类型分别为string和OSRefEx*,使用string作为key是为了满足应用场景以及方便对原引用表进行修改,比较重要的是作为value的

OSRefEx*类型。OSRefex的设计参考了原OSRef类,提取了3个重要的属性来作为其成员变量。mp_Object表示string对应的对象指针,m_Count表示了对引用对象的引用次数,而m_Cond用于安全的来进行引用和释放引用。

有了OSRefex的设计,那么对于引用表的操作就是一些简单的map的增、删、查询操作了,相信对照代码一定可以看的很明白。

源码在下载频道,如发现错误,欢迎指教。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值