// MemPoolT.h
* @date 2007.10.25
* @author PeakGao <[email protected]>
*/
#ifndef OM_MEMPOOLT_H
#define OM_MEMPOOLT_H
#include <assert.h>
#include <ace/guard_t.h>
#include <ace/global_macros.h>
namespace om{
/**//**
緩衝池
緩存池採取2維內存緩衝機制,每次new出一個緩衝鏈,每個緩衝鏈爲
<GrowBlockCount>個大小爲<BlockSize>的內存塊,緩衝鏈之間建立鏈表關
系。
優點:
1、緩衝池大小由小變大,動態增長,不是一開始就分配一個超大的內
存,真正按需分配;
2、不存在realloc,緩衝地址固定不變;
3、支持FreeList,高效;
缺點:
1、分配的對象在長時間不用時沒有實現智能釋放,以後有需要再改
要求:
1、每個塊的大小必須大於等於sizeof(Node),32位系統上面是4字節
示例:
@code
class MyObj
{
public:
MyObj()
{
std_out<<ACE_TEXT("MyObj::MyObj()")<<std_endl;
}
~MyObj()
{
std_out<<ACE_TEXT("MyObj::~MyObj()")<<std_endl;
}
void foo()
{
std_out<<ACE_TEXT("MyObj::foo()")<<std_endl;
}
int dummy;
};
void test()
{
using namespace om;
typedef CachePoolWithLock<ACE_Lock_Adapter<ACE_SYNCH_MUTEX> > CachePool_Lock;
CachePool p1;
p1.create(1024, 256);
void* pp1 = p1.alloc();
p1.free(pp1);
p1.clear();
CachePool_Lock p2(7, 256);
void* pp2 = p2.alloc();
p2.free(pp2);
p2.clear();
ObjectPool<MyObj, CachePool_Lock> pool(128);
MyObj* o = pool.alloc();
o->foo();
pool.free(o);
pool.clear();
}
@endcode
*/
#define BYTE_ALIGN_8 /// 是否支持塊尺寸8字節對齊的開關宏
/**//**
緩存池
這裏只實現邏輯,不考慮線程安全,線程安全的版本見下面的CachePoolWithLock模版
*/
class CachePool
{
protected:
/**//// 緩衝鏈: Head + cache1 + cache2 + cacheN (N=BlockCount)
struct Chain
{
Chain* _Next;
void* data() { return this + 1; }
inline static Chain* create(Chain*& head, size_t blockSize, size_t blockCount)
{
#if defined(BYTE_ALIGN_8)
blockSize = blockSize ? ((blockSize + 7) & ~7) : 8; // 8字節對齊
#endif
Chain* p = (Chain*) new char[sizeof(Chain) + blockCount * blockSize];
p->_Next = head;
return head = p;
}
void free()
{
Chain* p = this;
while (p)
{
char* buf = (char*)p;
Chain* next = p->_Next;
delete[] buf;
p = next;
}
}
};
/**//// 空閒對象節點,僅僅在空閒對象中有效
struct Node
{
Node* _Next;
};
size_t _BlockSize; /**//// 數據塊的字節大小
size_t _GrowBlockCount; /**//// 每次連續分配的塊數
Chain* _ChainList; /**//// 每次分配的緩衝鏈
Node* _FreeNode; /**//// 當前空閒節點
public:
/**//// 默認構造,注意必須調用create方法初始化參數
CachePool()
: _BlockSize(0), _GrowBlockCount(0), _ChainList(0), _FreeNode(0)
{
}
CachePool(size_t blockSize, size_t growBlockCount)
: _ChainList(0), _FreeNode(0)
{
create(blockSize, growBlockCount);
}
~CachePool()
{
clear();
}
/**//// 清除所有的內存空間
void clear()
{
if (_ChainList)
{
_ChainList->free();
_ChainList = 0;
_FreeNode = 0;
}
}
/**//// 初始化參數
void create(size_t blockSize, size_t growBlockCount)
{
_BlockSize = blockSize;
_GrowBlockCount = growBlockCount;
assert(_GrowBlockCount >= 1);
assert(_BlockSize >= sizeof(Node));
}
/**//// 獲取塊的大小
size_t getBlockSize() const
{
return _BlockSize;
}
/**//// 獲取連續分配的塊的數目
size_t getGrowBlockCount() const
{
return _GrowBlockCount;
}
/**//// 分配一個塊內存
void* alloc()
{
assert(_GrowBlockCount >= 1);
assert(_BlockSize >= sizeof(Node));
if (_FreeNode == 0)
{
// 分配另一個數據鏈
Chain* newChain = Chain::create(_ChainList, _BlockSize, _GrowBlockCount);
Node* node = (Node*)newChain->data();
// 定位到最後一個節點
(char*&)node += _BlockSize * (_GrowBlockCount - 1);
// 建立連接關係
for (int i=(int)_GrowBlockCount-1; i>=0; i--, (char*&)node -= _BlockSize)
{
node->_Next = _FreeNode;
_FreeNode = node;
}
}
assert(_FreeNode != 0);
void* block = (void*)_FreeNode;
_FreeNode = _FreeNode->_Next;
return block;
}
/**//// 釋放塊內存
void free(void* block)
{
if (block != 0)
{
Node* node = (Node*)block;
node->_Next = _FreeNode;
_FreeNode = node;
}
}
};
/**//**
支持鎖策略的緩存池,目前用的ACE的鎖,可以很方便的改爲其他的鎖策略
比如_ACELOCK可以爲鎖對象ACE_Lock_Adapter<ACE_SYNCH_MUTEX>,也可以
直接用互斥體如ACE_SYNCH_NULL_MUTEX
*/
template<class ACELOCK>
class CachePoolWithLock : public CachePool
{
protected:
ACELOCK _Lock; /**//// 鎖
public:
CachePoolWithLock()
{
}
CachePoolWithLock(size_t blockSize, size_t growBlockCount)
: CachePool(blockSize, growBlockCount)
{
}
/**//// 清除所有的內存空間
void clear()
{
ACE_GUARD(ACELOCK, ace_mon, _Lock);
CachePool::clear();
}
/**//// 分配一個塊內存
void* alloc()
{
ACE_GUARD_RETURN(ACELOCK, ace_mon, _Lock, NULL);
return CachePool::alloc();
}
/**//// 釋放塊內存
void free(void* block)
{
ACE_GUARD(ACELOCK, ace_mon, _Lock);
CachePool::free(block);
}
};
/**//**
對象池
在緩衝池的基礎上,增加了對象的構造和析構爲了更好擴充,模版參數直接傳入緩衝池類型,可
以是上面的CachePool、CachePoolWithLock,也可以是用戶自定義的緩衝池,但必須符合調用規範
*/
template<class T, class CachePoolStrategy>
class ObjectPool : public CachePoolStrategy
{
protected:
typedef CachePoolStrategy _Base;
public:
ObjectPool()
{
}
ObjectPool(size_t growBlockCount)
: _Base(sizeof(T), growBlockCount)
{
}
/**//// 初始化參數
void create(size_t growBlockCount)
{
_Base::create(sizeof(T), growBlockCount);
}
/**//// 創建對象的內存空間,但是沒有進行構造,用戶可以自行進行定製的構造
T* alloc()
{
void* obj = _Base::alloc();
::new (obj) T(); // 只提供了採用默認構造的方式
return (T*)obj;
}
/**//// 釋放對象
void free(T* obj)
{
if (obj != 0)
{
obj->~T();
_Base::free(obj);
}
}
};
} // namespace om
#endif // OM_MEMPOOLT_H