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);
}