C++11 使用可變參數模板類實現對象池

對象池模板類:

#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";
}

測試結果:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章