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

来源:互联网 发布:linux avi 转mp4 编辑:程序博客网 时间:2024/06/04 19:44

一直受惠于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为valueOSMutex         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,否则返回falsepublic: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 0