基于C++的内存池的实现

#ifndef MEMORYPOOL_H
#define MEMORYPOOL_H

#include<mutex>
static const int __align = 8;
static const int __max_bytes = 512;
static const int __number_of_free_lists = __max_bytes / __align;//内存池的数量
static const int __number_add_nodes = 20;
class MemoryPool
{
public:
    static MemoryPool& getInstance()
    {
        static MemoryPool pool;
        return pool;
    }
    void *allocMemory(size_t nSize);//分配内存
    void freeMemory(void*&pMem,size_t nsize);//释放内存
private:
    union MemNode
    {
        char index;//释放时,用于记录在那个内存池
        MemNode*    _next;//分配创建内存时用于连接各个内存块的
    };
    struct BigBloke//大内存块的连接地址
    {
        BigBloke *pPre;
        BigBloke *pNext;
        char index;//那个内存池
        char num;    //当前内存块的空间大小
    };
    MemoryPool();
    ~MemoryPool();

    int RoundUp(int size, int align = __align)
    {
        return ((size + align - 1) & ~(align - 1));//向8(align)字节的内存空间靠齐
    }

    int FreeListIndex(int size, int align = __align)
     {
        return (size + align - 1) / align - 1;//找到对应分配内存对应内存池下标
     }

    MemNode* MallocMemory(int size);//分配大内存块
    void FreeMemory(int index);//释放大内存块

private:
    size_t free_memory_size[__number_of_free_lists];//各个内存池的容量
    size_t use_memory_size[__number_of_free_lists];//各个内存池的使用情况
    MemNode*    _free_list[__number_of_free_lists];    //可用内存池列表
    BigBloke *pStart;
    BigBloke *pEnd;
protected:
   std::recursive_mutex _mutex;
};


void *operator new(size_t size);
void operator delete(void *p, size_t size);

void *operator new[](size_t size);

void operator delete[](void *p, size_t size);

#endif // MEMORYPOOL_H
 

//=================================================================================================

#include "Memorypool.h"
MemoryPool::MemoryPool()
{
    for (size_t i = 0; i < __number_of_free_lists; ++i)
    {
        free_memory_size[i] = 0;
        use_memory_size[i] = 0;
        _free_list[i] = nullptr;
    }
    pStart = nullptr;
    pEnd = nullptr;
}
MemoryPool::~MemoryPool()
{
    BigBloke *temp;
    while (pStart!=nullptr)
    {
        temp = pStart;
        pStart = pStart->pNext;
        free(temp);
    }
}
void *MemoryPool::allocMemory(size_t nSize)//分配内存
{
    int malloc_size = nSize;
    if (malloc_size > __max_bytes)
    {
        //大内存从系统中分配空间
        void* bytes = malloc(malloc_size);
        return bytes;
    }
    //小内存从系统中分配空间
    int index = FreeListIndex(malloc_size);
    std::unique_lock<std::recursive_mutex> lock(_mutex);
    MemNode** my_free = &(_free_list[index]);
    MemNode* result = *my_free;
    if (result == nullptr) 
    {
        //内存池空间已经用完,需重新分配
        result = MallocMemory(RoundUp(malloc_size));
        if (result == nullptr)
        {
            //分配内存失败
            return nullptr;
        }
    }
    *my_free = result->_next;
    use_memory_size[index] += 1;
    char *ret = (char*)result;
    return ret;
}

void MemoryPool::freeMemory(void*&pMem, size_t nsize)//释放内存
{
    if (pMem == nullptr)
        return;
    
    if (nsize>__max_bytes) //从系统中分配的大空间
    {
        free(pMem);
        return;
    }
    int index = FreeListIndex(nsize);
    //从内存池分配空间的释放
    MemNode* node = (MemNode*)pMem;
    std::unique_lock<std::recursive_mutex> lock(_mutex);
    MemNode** my_free = &(_free_list[index]);
    node->_next = *my_free;
    *my_free = node;
    pMem = nullptr;
    use_memory_size[index] -= 1;
    //当使用内存小到分配内存的一半时,释放一个大内存
    if ((free_memory_size[index]>(__number_add_nodes*2))&&(use_memory_size[index] < free_memory_size[index] * 0.5))
    {
        FreeMemory(index);
    }
}

MemoryPool::MemNode* MemoryPool::MallocMemory(int size)//每次内存池容量增加会以当前容量的0.5倍增加
{
    if (size % 8 != 0 || size <= 0)
        return nullptr;
    int num = 0;
    int index = FreeListIndex(size);
    //起初设定内存大小为20个内存块
    if (free_memory_size[index] == 0)
    {
        num = __number_add_nodes;
    }
    else
    {
        num = free_memory_size[index] * 0.5;
    }
    BigBloke *malloc_mem = (BigBloke *)malloc(num*size+sizeof(BigBloke));
    if (nullptr == malloc_mem)
        return nullptr;
    //将大内存块放人链表以便释放
    malloc_mem->index = index;
    malloc_mem->num = num;
    malloc_mem->pPre = pEnd;
    malloc_mem->pNext = nullptr;
    if (pEnd != nullptr)
    {
        pEnd->pNext = malloc_mem;
    }
    pEnd = malloc_mem;
    if (pStart == nullptr)
    {
        pStart = malloc_mem;
    }
    MemNode *re=(MemNode*)((char *)malloc_mem+sizeof(BigBloke));
    //内存连接
    MemNode *pNext = re,*temp=nullptr;
    for(size_t i=1;i<num;++i)
    {
        temp = (MemNode *)((char*)re + i*size);
        temp->_next = nullptr;
        pNext->_next = temp;
        pNext = temp;
    }
    //修改内存池的大小
    free_memory_size[FreeListIndex(size)] += num;
    return re;
}
void MemoryPool::FreeMemory(int index)//释放大内存块
{
    
    BigBloke *p = pEnd;
    while (p != nullptr)
    {
        if (p->index == index)
        {
            BigBloke *pre = p->pPre;
            if (pre != nullptr)
            {
                pre->pNext = p->pNext;
                if(p->pNext!=nullptr)
                    p->pNext->pPre = pre;
            }
            else//删除头
            {
                pStart = p->pNext;
                if (pStart == nullptr)
                {
                    pEnd = nullptr;
                }
            }
            free_memory_size[index] -= p->num;
            free(p);//删除内存大块
            break;
        }
        p = p->pPre;
    }
}


    void *operator new(size_t size)
    {
        return MemoryPool::getInstance().allocMemory(size);
    }

    void operator delete(void *p,size_t size)
    {
        MemoryPool::getInstance().freeMemory(p,size);
    }

    void *operator new[](size_t size)
    {
        return MemoryPool::getInstance().allocMemory(size);
    }

    void operator delete[](void *p, size_t size)
    {
        MemoryPool::getInstance().freeMemory(p,size);
    }
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值