这其实还是参照对象池的设计思想
这个对象索引的实现,我们也可以把它叫做索引池,索引结点的个数可以由Allocator负责动态增加
而它具有和对象池一模一样的分配子TObjectAllocator
只不过这里TObjectAllocator分配的链表结点,内部再嵌套了一个树节点
m_Used不再是对象池中所定义的TBDLinkList<T>,而是TTree<K, T>
m_Free则定义为TBDLinkList<TLeaf<K, T>>
索引没有m_Assign
索引提供T *Find(K& key)来支持对m_Used的查找,内部调用的实际上是AVL树的TLeaf<K, T> *Find(K& key);
下面贴出具体代码
TObjectIndex.h:
#ifndef _TObjectIndex_h_
#define _TObjectIndex_h_
#include <windows.h>
#include "TTree.h"
#include "TObjectAllocator.h"
#include "CLock.h"
#include "tool.h"
//索引
template <class K, class T>
class TObjectIndex
{
public:
TObjectIndex();
~TObjectIndex();
//初始化\清空索引
public:
bool Init(DWORD dwFirstObjCount,
DWORD dwAddObjCount,
ContainerFlag dwLock = enum_EnableLock);
//释放索引的所有分配子
public:
void Release();
//对象索引池索引结点不够时,增加分配子,开辟新内存
private:
bool AddObject(DWORD dwAddCount);
//从空闲列表Free得到一个对象索引结点,对其赋值,放入使用列表Used
public:
bool Malloc(K& key, T& obj);
//在使用列表Used中搜索key指定的结点
public:
T *Find(K& key);
//将指定对象索引结点从使用列表Used,放入空闲列表Free
public:
bool Free(K& key);
//获取当前各个列表使用情况
public:
DWORD GetUsedListLen();
DWORD GetFreeListLen();
private:
TTree<K, T> m_Used;//可以正常使用的对象列表
TBDLinkList<TLeaf<K, T>> m_Free;//空闲对象列表
TBDLinkList<TObjectAllocator<TLeaf<K, T>>> m_MemAllocList;//对象池分配子管理链表
DWORD m_dwAddObjCount;
CLock m_csLock; //临界区,保证池操作的线程安全
ContainerFlag m_dwLock; //是否使用临界区进行加锁
};
#include "TObjectIndex.hpp"
#endif
TObjectIndex.hpp:
#ifndef _TObjectIndex_hpp_
#define _TObjectIndex_hpp_
template <class K, class T>
TObjectIndex<K, T>::TObjectIndex()
{
m_Used.Init(enum_DisableLock);
m_Free.Init(enum_DisableLock);
m_MemAllocList.Init(enum_DisableLock);
m_dwAddObjCount = 0;
m_dwLock = enum_DisableLock;
}
template <class K, class T>
TObjectIndex<K, T>::~TObjectIndex()
{
Release();
}
template <class K, class T>
bool TObjectIndex<K, T>::Init(DWORD dwFirstObjCount,
DWORD dwAddObjCount,
ContainerFlag dwLock)
{
if (0 == dwFirstObjCount)
{
//初始化参数不正确
return false;
}
else
{
m_dwAddObjCount = dwAddObjCount;
m_dwLock = dwLock;
//申请分配子,开辟第一块内存
return AddObject(dwFirstObjCount);
}
}
template <class K, class T>
void TObjectIndex<K, T>::Release()
{
m_Used.Init(enum_DisableLock);
m_Free.Init(enum_DisableLock);
TBDLinker<TObjectAllocator<TLeaf<K, T>>> *pLinker = m_MemAllocList.PopHead();
while (NULL != pLinker)
{
delete pLinker;
pLinker = m_MemAllocList.PopHead();
}
m_MemAllocList.Init(enum_DisableLock);
m_dwAddObjCount = 0;
m_dwLock = enum_DisableLock;
}
template <class K, class T>
bool TObjectIndex<K, T>::AddObject(DWORD dwAddCount)
{
if (0 == dwAddCount)
{
return false;
}
else
{
TBDLinker<TObjectAllocator<TLeaf<K, T>>> *pLeaf = new TBDLinker<TObjectAllocator<TLeaf<K, T>>>;
if (NULL == pLeaf)
{
return false;
}
pLeaf->Init();
if (!pLeaf->m_Value.Init(dwAddCount, m_Free))
{
delete pLeaf;
return false;
}
m_MemAllocList.PushTail(pLeaf);
return true;
}
}
template <class K, class T>
bool TObjectIndex<K, T>::Malloc(K& key, T& obj)
{
if (enum_EnableLock == m_dwLock)
{
m_csLock.Lock();
}
TBDLinker<TLeaf<K, T>> *pLinker = m_Free.PopHead();
if (NULL == pLinker)
{
if (AddObject(m_dwAddObjCount))
{
pLinker = m_Free.PopHead();
}
}
if (NULL == pLinker)
{
if (enum_EnableLock == m_dwLock)
{
m_csLock.UnLock();
}
return false;
}
else
{
TLeaf<K, T> *pLeaf = &(pLinker->m_Value);
pLeaf->m_Key = key;
pLeaf->m_Value = obj;
m_Used.Insert(pLeaf);
if (enum_EnableLock == m_dwLock)
{
m_csLock.UnLock();
}
return true;
}
}
template <class K, class T>
T *TObjectIndex<K, T>::Find(K& key)
{
T *obj = NULL;
if (enum_EnableLock == m_dwLock)
{
m_csLock.Lock();
}
TLeaf<K, T> *pLeaf = m_Used.Find(key);
if (NULL != pLeaf)
{
obj = &(pLeaf->m_Value);
}
if (enum_EnableLock == m_dwLock)
{
m_csLock.UnLock();
}
return obj;
}
template <class K, class T>
bool TObjectIndex<K, T>::Free(K& key)
{
bool bRes = false;
if (enum_EnableLock == m_dwLock)
{
m_csLock.Lock();
}
TLeaf<K, T> *pLeaf = m_Used.Find(key);
if (NULL != pLeaf)
{
TBDLinker<TLeaf<K, T>> *pLinker = ContainerOf(pLeaf, TBDLinker<TLeaf<K TEMPLATE_COMMA T>>, m_Value);
m_Used.Remove(pLeaf);
m_Free.PushTail(pLinker);
bRes = true;
}
if (enum_EnableLock == m_dwLock)
{
m_csLock.UnLock();
}
return bRes;
}
template <class K, class T>
DWORD TObjectIndex<K, T>::GetUsedListLen()
{
return m_Used.GetLen();
}
template <class K, class T>
DWORD TObjectIndex<K, T>::GetFreeListLen()
{
return m_Free.GetLen();
}
#endif