對象池模板類:
#pragma once
#include "CObjInstance.h"
#include <mutex>
#include <vector>
#include <map>
/// <summary>
/// 實現模板類型對象池,使其可以適配任何類類型且是線程安全的!!!
/// </summary>
template<class T>
class CObjPool
{
public:
CObjPool() {}
~CObjPool()
{
if (m_poolMemoryHeader)
{
//先釋放對象內存
while (m_pRootNode)
{
delete (T*)(m_pRootNode->pObjInstance);
m_pRootNode = m_pRootNode->pNext;
}
//再釋放node的內存
delete[] m_poolMemoryHeader;
m_poolMemoryHeader = nullptr;
}
}
/// <summary>
/// 每個對象的頭節點
/// </summary>
struct HeadNode
{
char* pObjInstance; //obj實例指針
HeadNode* pNext; //下一個obj實例指針
size_t nRefCount; //obj引用次數
size_t nID; //obj的ID
};
/// <summary>
/// 獲取對象池的對象數
/// </summary>
/// <returns></returns>
int GetPoolSetObjCount()
{
return m_poolObjCount;
}
/// <summary>
//初始化對象池
/// </summary>
template<typename... Args>
void InitObjPool(int nObjCount, Args... args)
{
if (nObjCount <= 0)
{
return;
}
//初始化使用內存
size_t nUseMemorySize = nObjCount * (sizeof(HeadNode)); //一次性分配內存池對象需要使用的總內存(對象自己的內存除外)
m_poolMemoryHeader = new char[nUseMemorySize];
memset(m_poolMemoryHeader, 0, nUseMemorySize * sizeof(char));
//初始化跟節點
char* tempMemoryHeader = m_poolMemoryHeader;
m_pRootNode = InitHeadNode(tempMemoryHeader);
tempMemoryHeader = tempMemoryHeader + (sizeof(HeadNode));
m_pRootNode->nID = 1;
m_pRootNode->pObjInstance = (char*)(new T(args...));
//tempMemoryHeader += sizeof(T);
m_mapFreeNode[m_pRootNode->nID] = m_pRootNode;
//初始化其它節點
HeadNode* tempNode = m_pRootNode;
for (int i = 1; i < nObjCount; i++)
{
HeadNode* node = InitHeadNode(tempMemoryHeader);
tempMemoryHeader = tempMemoryHeader + (sizeof(HeadNode));
node->pObjInstance = (char*)(new T(args...));
node->nID = tempNode->nID + 1;
m_mapFreeNode[node->nID] = node;
//tempMemoryHeader += sizeof(T);
tempNode->pNext = node;
tempNode = node;
}
m_poolObjCount = nObjCount;
}
//獲取使用對象
T* NewObjInstance()
{
std::lock_guard<std::mutex> lg(m_mutex);
//從對象池中取可用的對象,若無可用返回空
T* obj = nullptr;
if (m_mapFreeNode.empty())
{
return obj;
}
HeadNode* node = (*m_mapFreeNode.begin()).second;
obj = (T*)(node->pObjInstance);
node->nRefCount++;
m_mapFreeNode.erase(m_mapFreeNode.begin());
return obj;
}
//釋放使用對象
void DeleteObjInstance(void* p)
{
HeadNode* node = m_pRootNode;
while (node)
{
if (node->pObjInstance == p)
{
break;
}
node = node->pNext;
}
if (node == nullptr)
{
return;
}
node->nRefCount--;
if (node->nRefCount == 0)
{
std::lock_guard<std::mutex> lg(m_mutex);
m_mapFreeNode[node->nID] = node;
}
}
private:
//初始化HeadNode
HeadNode* InitHeadNode(char* p)
{
HeadNode* node = (HeadNode*)p;
node->nRefCount = 0;
node->pNext = nullptr;
node->nID = 0;
return node;
}
private:
int m_poolObjCount = 0; //對象池中的對象總數
char* m_poolMemoryHeader = nullptr; //對象池內存起始地址
HeadNode* m_pRootNode = nullptr; //對象池根節點
std::map<size_t, HeadNode*> m_mapFreeNode; //空閒obj節點 key:節點ID value: 節點指針
std::mutex m_mutex; //申請obj鎖
};
測試代碼:
```cpp
#include <iostream>
#include "CObjPool.h"
class A
{
public:
A(int n)
{
a = n;
}
~A()
{
std::cout << "~A" << std::endl;
}
public:
int a = 0;
};
class B
{
public:
B(int n, int m)
{
a = n;
b = m;
}
~B()
{
std::cout << "~B" << std::endl;
}
public:
int a = 0;
int b = 0;
};
void Test()
{
CObjPool<A>* poolA = new CObjPool<A>();
poolA->InitObjPool(10, 6);
A* a1 = poolA->NewObjInstance();
a1->a = 1;
A* a2 = poolA->NewObjInstance();
a2->a = 2;
A* a3 = poolA->NewObjInstance();
poolA->DeleteObjInstance(a1);
poolA->DeleteObjInstance((char*)a2);
a3 = poolA->NewObjInstance();
a3->a = 3;
poolA->DeleteObjInstance(a3);
delete poolA;
poolA = nullptr;
CObjPool<B>* poolB = new CObjPool<B>();
poolB->InitObjPool(10, 6, 9);
B* b1 = poolB->NewObjInstance();
std::cout << b1->a << b1->b << std::endl;
poolB->DeleteObjInstance(b1);
b1 = nullptr;
b1 = poolB->NewObjInstance();
b1->a = 3;
b1->b = 3;
std::cout << b1->a << b1->b << std::endl;
poolB->DeleteObjInstance(b1);
delete poolB;
poolB = nullptr;
}
int main()
{
Test();
std::cout << "Hello World!\n";
}
測試結果: