内存池
1. 内存池设计
1.1 目的
在给定的内存buffer上建立内存管理机制,根据用户需求从该buffer上分配内存或者将已经分配的内存释放回buffer中。
1.2 要求
尽量减少内存碎片,平均效率高于C语言的malloc和free。
1.3 设计思路
- 一个存储全部内存的容器
 - 一个存储正在使用的内存的容器
 - 一个存储未被使用的容器
 
实现
#ifndef TESTJSON_MEMORYPOOL_HPP
#define TESTJSON_MEMORYPOOL_HPP
#include <algorithm>
#include <functional>
#include <set>
#include <vector>
#include <queue>
#include <cstdlib>
#include <cxxabi.h>
template<typename T>
class MemoryPool
{
public:
    MemoryPool();
    MemoryPool(int max_size);
    virtual ~MemoryPool();
    T *alloc();
    void release(T *obj);
    void walkUsedMemList(std::function<void(T *)> func);
private:
    static int ALLOC_STEP;
    int mMaxSize;
    int mCurrentSize;
    std::queue<T *> mFreeMemList;
    std::set<T *> mUsedMemList;
    int newMemList(int size);
};
template<class T>
int MemoryPool<T>::ALLOC_STEP = 20;
template<class T>
MemoryPool<T>::MemoryPool()
{
    this->mCurrentSize = 0;
    this->mMaxSize = 0;
    this->newMemList(ALLOC_STEP);
}
template<class T>
MemoryPool<T>::MemoryPool(int max_size)
{
    this->mCurrentSize = 0;
    this->mMaxSize = max_size;
    this->newMemList(ALLOC_STEP);
}
template<class T>
MemoryPool<T>::~MemoryPool()
{
    for_each(mUsedMemList.begin(), mUsedMemList.end(), [&](T *mem)
    {
        free(mem);
    });
    int queue_size = mFreeMemList.size() ;
    for (int i = 0; i < queue_size; ++i)
    {
        auto mem = mFreeMemList.front();
        free(mem);
        mFreeMemList.pop();
    }
}
template<class T>
void MemoryPool<T>::walkUsedMemList(std::function<void(T *)> func)
{
    for_each(mUsedMemList.begin(), mUsedMemList.end(), [&](T *mem)
    {
        func(mem);
    });
}
template<class T>
int MemoryPool<T>::newMemList(int size)
{
    if (this->mMaxSize > 0)
    {
        int left = this->mMaxSize - this->mCurrentSize;
        if (left == 0)
            return 0;
        size = size < left ? size : left;
    }
    for (int i = 0; i < size; i++)
    {
        T *mem = (T *) malloc(sizeof(T));
        if (!mem)
        {
            printf("malloc failed! total size : %d \n", mCurrentSize);
            return 0;
        }
        mFreeMemList.push(mem);
    }
    this->mCurrentSize += size;
    // ???
//    printf("pool add objs : %s pool , total size : %d\n", abi::__cxa_demangle(typeid(T).name(), 0, 0, 0), mCurrentSize);
    return size;
}
template<class T>
T *MemoryPool<T>::alloc()
{
    if (mFreeMemList.empty())
    {
        if (newMemList(ALLOC_STEP) == 0)
        {
            return NULL;
        }
    }
    T *obj = mFreeMemList.front();
    mUsedMemList.insert(obj);
    mFreeMemList.pop();
    return obj;
}
template<typename T>
inline void MemoryPool<T>::release(T *obj)
{
    if (mUsedMemList.erase(obj))
    {
        mFreeMemList.push(obj);
    }
}
#endif //TESTJSON_MEMORYPOOL_HPP