【C++服务端技术】对象池

代码没贴全,就少一个锁头文件,可以做设计参考

设计思想就是维护一个空闲链表,没有用的就重新申请,有的话就拿链表的头,使用完又还给空闲链表。

/*
一个分配固定大小内存的内存池,使用链表维护

*/
#pragma once
#include
using namespace std;
#include "../Thread/AutoLock.h"
using namespace Extralib::Thread;

struct Link
{
    Link* m_pNext;
};

const int DEFAULT_SIZE = 100;

// T的大小不能小于4个字节
template
class MemoryPool
{
public:
    MemoryPool();                   // 默认
    MemoryPool(int nSize);          // 内存池个数
    ~MemoryPool();                  // 析构

    T*      New();                  // 获得一个没有用过的内存
    void    Delete(T* pBuff);       // 释放一个内存
    void    Recycle();

    unsigned int GetAllCount();
    unsigned int GetUsedCount();

    const char* GetDesc();
private:
    void    Init();
    void    CreateMemory();// 分配内存

    int         m_nAll;             // 所有分配的个数,统计使用
    int         m_nNum;             // 当前使用的个数
    pthread_mutex_t m_mutex;        // 互斥锁
    Link*       m_pFree;            // 空闲列表
    set m_MemBlockList;     // 所有分配的大的内存块,用于删除

    //用于统计计数
    int m_delCount;
    int m_newCount;
    char m_DescBuffer[256];
};

template
MemoryPool::MemoryPool()
{
    Init();
}

template
MemoryPool::MemoryPool(int nSize)
{
    Init();
    AutoLock locker(m_mutex);

    for(int i = 0; i < nSize ; ++i)
    {
        CreateMemory();
    }

}

template
void MemoryPool::Init()
{
    Debug_Assert(sizeof(T) > sizeof(char*));
    pthread_mutex_init(&m_mutex,0);
    m_nAll = 0;
    m_nNum = 0;
    m_pFree = 0;

    m_delCount = 0;
    m_newCount = 0;
};

template
const char* MemoryPool::GetDesc()
{
    AutoLock locker(m_mutex);
    sprintf(m_DescBuffer,"(All:%d,Used:%d,NewCount:%d,DelCount:%d)",m_nAll,m_nNum,m_newCount,m_delCount);

    return m_DescBuffer;
}

template
MemoryPool::~MemoryPool()
{
    set::iterator itor;
    for(itor = m_MemBlockList.begin(); itor != m_MemBlockList.end(); ++itor)
    {
        delete[] (*itor);
    }

    m_MemBlockList.clear();
}

template< typename T>
void MemoryPool::CreateMemory()
{
    int nSize = 1;

    // 所有分配的内存快
    m_nAll += nSize;
    char* pData = new char[nSize * sizeof(T)];
    m_MemBlockList.insert(pData);

    // 结尾连接到当前
    Link* pTail = (Link*)(pData + sizeof(T) * (nSize - 1));
    pTail->m_pNext = m_pFree;
    // 串起来内存
    m_pFree = (Link*)pData;
    Link* pNode = m_pFree;
    for(int i = 0; i < nSize - 1; ++i)
    {
        pNode->m_pNext = (Link*)(pData + (sizeof(T) * (i + 1)));
        pNode = pNode->m_pNext;
    }
}

template< typename T >
T* MemoryPool::New()
{
    AutoLock locker(m_mutex);
    if( !m_pFree )
    {
        CreateMemory();
    }

    if(m_pFree)
    {
        m_nNum++;
        m_newCount ++;

        Link* pHead = m_pFree;
        m_pFree = m_pFree->m_pNext;
        new(pHead)T;    //调用对象的构造函数
        return (T*)pHead;
    }

    return 0;
}

template
void MemoryPool::Delete(T* pBuff)
{
    AutoLock locker(m_mutex);
    m_nNum--;

    m_delCount ++;

    pBuff->~T();
    Link* pLink = (Link*)pBuff;
    pLink->m_pNext = m_pFree;
    m_pFree = pLink;
}

template
void MemoryPool::Recycle()
{
    AutoLock locker(m_mutex);

    while(m_pFree)
    {
        Link* pHead = m_pFree;
        m_pFree = m_pFree->m_pNext;
        m_MemBlockList.erase((char*)pHead);

        m_nAll--;
    }

}

template
unsigned int MemoryPool::GetAllCount()
{
    AutoLock locker(m_mutex);
    return m_nAll;
}

template
unsigned int MemoryPool::GetUsedCount()
{
    AutoLock locker(m_mutex);
    return m_nNum;
}

Original: https://www.cnblogs.com/byfei/p/14104066.html
Author: byfei
Title: 【C++服务端技术】对象池

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/535130/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • std::get<C++11多线程库~线程间共享数据>(09):共享数据带来的问题(1)

    1 #include 2 3 /* 4 * 话题1:线程间共享数据 5 * a. 共享数据带来的问题 6 * b. 使用互斥量保护数据 7 * c. 数据保护的替代方案 8 * 9…

    C++ 2023年5月29日
    056
  • C++11:lambda表达式详细介绍

    优点如下: 声明式编程风格:就地匿名定义目标函数或函数对象,有更好的可读性和可维护性。 简洁:不需要额外写一个命名函数或函数对象,,避免了代码膨胀和功能分散。 更加灵活:在需要的时…

    C++ 2023年5月29日
    047
  • [UE4]虚幻引擎的C++环境安装

    一、一般使用VS2017开发 二、需要勾选”使用C++的游戏开发” posted on2019-03-08 17:02 一粒沙 阅读(2513 ) 评论()…

    C++ 2023年5月29日
    049
  • C++中的friend函数详细解析(二)

    一.设计模式 单例模式(类只能生成一个对象) 屏蔽构造函数,拷贝构造函数(放在private中 类外无法访问),此时类外就无法看到这两个函数了 也就无法生成对象了 类就没有意义了 …

    C++ 2023年5月29日
    055
  • GCC:/usr/lib/libstdc++.so.6: version GLIBCXX_3.4.15 not found

    源码编译升级安装了gcc后,编译程序或运行其它程序时,有时会出现类似/usr/lib64/libstdc++.so.6: version GLIBCXX_3.4.15' …

    C++ 2023年5月29日
    083
  • c++builder调用VC的dll以及VC调用c++builder的dll

    解析__cdecl,__fastcall, __stdcall 的不同:在函数调用过程中,会使用堆栈,这三个表示不同的堆栈调用方式和释放方式。比如说__cdecl,它是标准的c方法…

    C++ 2023年5月29日
    066
  • C++ mutable的用法

    mutalbe的中文意思是”可变的,易变的”,跟constant(既C++中的const)是反义词。 在C++中,mutable也是为了突破const的限制…

    C++ 2023年5月29日
    051
  • C++ 内联函数解析(inline)

    inline是C++语言中的一个关键字,可以用于程序中定义内联函数,inline的引进使内联函数的定义更加简单。说到内联函数,这里给出比较常见的定义,内联函数是C++中的一种特殊函…

    C++ 2023年5月29日
    045
  • Kruskal算法(二)之 C++详解

    在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的最小生成树。 例如,对于如上图G4所示的连通网可以有多棵…

    C++ 2023年5月29日
    058
  • C++17新特性

    C++17新特性 前言 If Statements with Initializer Constexpr if inline 变量 嵌套命名空间 属性说明符 [[fallthrou…

    C++ 2023年5月29日
    050
  • c和c++开发工具之clion和vs

    个人体验结果 如果是CMake或者要跨平台的话,建议使用CLion 像我在看书写练习题的话,Clion使用cmake编译c/c++源码更简单上手使用。 如果项目不大,两者都可以。如…

    C++ 2023年5月29日
    0121
  • 转:TinyXM–优秀的C++ XML解析器

    include include “tinyxml.h” include “tinystr.h” include include in…

    C++ 2023年5月29日
    047
  • c++中CreateEvent函数

    函数原型: HANDLE CreateEvent( LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL…

    C++ 2023年5月29日
    059
  • vscode c++ 编译生成后,调试时无法命中断点

    1 //test.cpp 2 #include 3 int g_var = 0; 4 void print_line(char *str) 5 { 6 if (str != NUL…

    C++ 2023年5月29日
    065
  • c++ 异常 discards qualifiers 丢弃

    src/feedbackservice.cpp:76: error: passing const ps::spider::urlreceiver::entry::ConfigMan…

    C++ 2023年5月29日
    037
  • (筆記) 如何寫入binary file某個byte的值? (C/C++) (C)

    Abstract通常公司為了保護其智慧財產權,會自己定義檔案格式,其header區會定義每個byte各代表某項資訊,所以常常需要直接對binary檔的某byte直接進行寫入。 In…

    C++ 2023年5月29日
    048
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球