信息化 频道

企业信息化成功 要素及风险状况分析


其他方法的局限性

    当然,也有其他人编写了内存池类用于解决CRT堆开销过多的问题,然而,大多数这类方法需要大量修改现有程序的代码,以便让所有对new、delete的调用,都转向对缓冲池类成员的调用;另外,这类方法还有一个潜在的局限性,它们缺乏线程安全,而CFixedAlloc就是为了解决这些情况而来的。

    CFixedAlloc的类声明:
class CFixedAlloc 
{
//构造函数
public:
CFixedAlloc(UINT nAllocSize, UINT nBlockSize = 64);

//属性
UINT GetAllocSize() { return m_nAllocSize; }

//具体操作
public:
void* Alloc(); //返回一块nAllocSize大小的内存
void Free(void* p); //释放由Alloc分配的一块内存
void FreeAll(); //释放所有此类分配的内存

//实现
public:
~CFixedAlloc();

protected:
struct CNode
{
CNode* pNext;
};

UINT m_nAllocSize; //Alloc中每个块的大小
UINT m_nBlockSize; //每次获取的块数
CPlex* m_pBlocks; //块链表(nBlocks*nAllocSize)
CNode* m_pNodeFree; //第一个要释放的节点,如果没有则为NULL
CRITICAL_SECTION m_protect;
};
    可以看到,这是一个非常简单的类,而且,你也许也留意到了,这个类由临界区提供了线程安全。m_AllocSize中包含了类的对象大小,m_blockSize指定了每个固定内存块能包含的对象数,这两个成员都在构造函数中设置。唯一剩下的就是CPlex指针了,在这不打算详细讲解这个类,只需了解它才是真正进行CRT动态内存分配的类就行了,它包含了一个指针,指向另一个CPlex对象以创建一个CPlex链表,所以它的大小只能为4字节,当进行内存分配时,就需要m_allocSize*m_blockSize+sizeof(CPlex)。

    现在,我们可以对比CRT与CFixedAlloc之间的差异了:使用CRT,对于每个对象都会存在CRT开销;而使用CFixedAlloc,内存开销则为CRT开销加上CPlex大小(4字节),再除以已分配对象数,当分配数目非常大时,此开销接近于零。下面,再来仔细看一下两个更重要的CFixedAlloc函数:

void* CFixedAlloc::Alloc()
{
EnterCriticalSection(&m_protect);
if (m_pNodeFree == NULL)
{
CPlex* pNewBlock = NULL;
TRY
{
//添加另一个块
pNewBlock = CPlex::Create(m_pBlocks, m_nBlockSize, m_nAllocSize);
}
CATCH_ALL(e)
{
LeaveCriticalSection(&m_protect);
THROW_LAST();
}
END_CATCH_ALL

//把它们放进要释放的列表中
CNode* pNode = (CNode*)pNewBlock->data();
//逆向进行释放以便于调试
(BYTE*&)pNode +=
(m_nAllocSize * m_nBlockSize) - m_nAllocSize;
for (int i = m_nBlockSize-1; i >= 0; i--,
(BYTE*&)pNode -= m_nAllocSize)
{
pNode->pNext = m_pNodeFree;
m_pNodeFree = pNode;
}
}
ASSERT(m_pNodeFree != NULL);

//移除释放列表中第一个节点
void* pNode = m_pNodeFree;
m_pNodeFree = m_pNodeFree->pNext;

LeaveCriticalSection(&m_protect);
return pNode;
}

void CFixedAlloc::Free(void* p)
{
if (p != NULL)
{
EnterCriticalSection(&m_protect);

//把节点返回到释放列表中
CNode* pNode = (CNode*)p;
pNode->pNext = m_pNodeFree;
m_pNodeFree = pNode;
LeaveCriticalSection(&m_protect);
}
}

0
相关文章