c++ 11 簡約版內存池實現

c++ 11 簡約版內存池實現

使用c++11的智能指針實現一個簡約版的內存池

.h文件
//
// Created by ilong on 2019/10/18.
//

#ifndef SRC_MEMORY_POOL_H
#define SRC_MEMORY_POOL_H

#include <list>
#include <map>
#include <mutex>
#include <memory>

constexpr static int kMaxBufferCount = 30;
constexpr static int kWarningFreeBufferCount = 2;

template <class T>
class MemoryPool{
public:
    MemoryPool(int maxCount = kMaxBufferCount, const std::string &tag = "");
    ~MemoryPool();
    std::shared_ptr<T> GetObject();
    void ReleaseObject(std::shared_ptr<T> data);
    void ClearAllObjects();
    int GetFreeCount();
    int GetUsedCount();
private:
    std::list<std::shared_ptr<T>> free_list_;
    std::map<T*, std::shared_ptr<T>> used_map_;
    std::mutex mutex_;
    int max_buffer_count_;

    std::string tag_;
    uint64_t last_warning_time_;
};
#endif //SRC_MEMORY_POOL_H

.cpp文件
//
// Created by ilong on 2019/10/18.
//

#include "memory_pool.h"
#include <chrono>

#define kReleaseIntervalTimeMS       10*1000

static uint64_t GetTimestampMs() {
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
    return ms.count();
}

template <class T>
DEFINE_LOGGER(MemoryPool<T>, "media.vhall.MemoryPool");

template <class T>
MemoryPool<T>::MemoryPool(int maxCount, const std::string &tag)
:max_buffer_count_{maxCount},
last_warning_time_{0},
tag_{tag}{

}

template <class T>
MemoryPool<T>::~MemoryPool() {

}

template <class T>
std::shared_ptr<T> MemoryPool<T>::GetObject(){
    std::lock_guard<std::mutex> guard(mutex_);
    int used_count = used_map_.size();
    if(used_count > kMaxBufferCount){
        ELOG_WARN("MemPool buffer count more than max count: %d", max_buffer_count_);
        std::shared_ptr<T> data;
        return data;
    }
    if(free_list_.size() > 0){
        std::shared_ptr<T> data = free_list_.front();
        free_list_.pop_front();
        used_map_[data.get()] = data;
        return data;
    } else{
        std::shared_ptr<T> data = std::make_shared<T>();
        used_map_[data.get()] = data;
        return data;
    }
}

template <class T>
void MemoryPool<T>::ReleaseObject(std::shared_ptr<T> data){
    std::lock_guard<std::mutex> guard(mutex_);
    if(used_map_.erase(data.get()) == 0){
        ELOG_WARN("release object was not found.");
    }
    int free_count = free_list_.size();
    if(free_count > kWarningFreeBufferCount){
        if(last_warning_time_ == 0){
            last_warning_time_ = GetTimestampMs();
        }
        if((GetTimestampMs()-last_warning_time_) < kReleaseIntervalTimeMS){
            free_list_.push_back(data);
        } else{
            last_warning_time_ = 0;
            ELOG_WARN("%s the free list is too long to release this object. free_count: %d", tag_, free_count);
        }
    } else{
        free_list_.push_back(data);
        last_warning_time_ = 0;
    }
}

template <class T>
void MemoryPool<T>::ClearAllObjects(){
    std::lock_guard<std::mutex> guard(mutex_);
    free_list_.clear();
    used_map_.clear();
}

template <class T>
int MemoryPool<T>::GetFreeCount(){
    std::lock_guard<std::mutex> guard(mutex_);
    return free_list_.size();
}

template <class T>
int MemoryPool<T>::GetUsedCount(){
    std::lock_guard<std::mutex> guard(mutex_);
    return used_map_.size();
}
測試程序
#include "memory_pool.cpp"

class DataBuffer{
public:
    DataBuffer(){

    }
};
int main() {
   MemoryPool<DataBuffer> memoryPool;
   for(int i = 0; i < 10; i++){
        auto data = memoryPool.GetObject();
        if(i > 3){
            memoryPool.ReleaseObject(data);
        }
    }
    int count = memoryPool.GetFreeCount();
    ELOG_DEBUG("Memory Pool Count: %d", count);
    auto data = memoryPool.GetObject();
    count = memoryPool.GetFreeCount();
    ELOG_DEBUG("Memory Pool Count: %d", count);
    memory_pool_.ClearAllObjects();
    count = memoryPool.GetFreeCount();
    ELOG_DEBUG("Memory Pool Count: %d", count);
}
注意由於模版類是寫在.h和.cpp文件中,所以使用是要 #include “memory_pool.cpp”,否則編譯會報錯
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章