内存池--高效实现

来源:互联网 发布:西澳大学 知乎 编辑:程序博客网 时间:2024/06/05 14:55

内存池主要分为三个部分:class buffer_t,class bufferpool_t,class mempool_t

1.class mempool_t:内存开辟与释放的接口,既可以通过内存池开辟释放或者在超过内存池最大内存分配大小时,通过系统进行开辟与释放。

2.class bufferpool_t:在mempool_t中申请的实际内存大小2^n(2^n<=最大内存分配大小)内存池)对应于一个bufferpool_t,一个bufferpool_t由list链表来管理多个2^n大小的内存块

3.class buffer_t:对实际内存块进行管理与存储。

话不多说,直接上源代码。

class mempool_t:

#include "bufferpool_t.h"class mempool_t{public:static mempool_t *get_instance();/*申请内存@param uint32_t size_ 内存大小   如果size_ 大与max_alloc_size 将重系统请求内存*/void *alloc(uint32_t size_);/*释放内存@param void* 内存句柄*/bool free(void* ptr);/*配置内存池最大内存分配大小@param uint32_t max_alloc_size.如果 mempool_t.alloc (size):其中 size > max_alloc_size内存池将重系统分配内存,但是 释放的时候 也一定要调用mempool_t.free 来释放,否则会内存错误*/void config(const uint32_t &max_alloc_size = 1<<20);private:mempool_t(void);~mempool_t(void);typedef std::map<uint32_t ,bufferpool_t *> bufferpool_set_t;bool get_bufferpool_size( uint32_t size_, uint32_t &buf_size_ );/*向系统请求分配内存  @param uint32_t size_ 内存大小  @return void* 内存句柄*/void * internal_malloc( const uint32_t &size_ );/*直接释放内存  @param void *ptr_ 内存句柄  @return bool true成功, false失败,原因是内存不是internal_malloc返回的,  或是内存已经被破坏了*/bool internal_free(void *ptr_);bufferpool_set_t bufferpool_set;uint32_t max_alloc_size;std::mutex bufferpool_set_mutex;};
#include "stdafx.h"#include "mempool_t.h"mempool_t::mempool_t(void):max_alloc_size(1<<20)//1MB{}mempool_t::~mempool_t(void){while (bufferpool_set.empty()==false){bufferpool_t *bufferpool = bufferpool_set.begin()->second;bufferpool_set.erase(bufferpool_set.begin());delete bufferpool;}}//设置内存分配对象的实例mempool_t * mempool_t::get_instance(){static mempool_t *instance = new mempool_t;return instance;}void * mempool_t::alloc( uint32_t size_ ){uint32_t buf_size;void *buf;bool rc = get_bufferpool_size(size_,buf_size);if (rc){bufferpool_t *bufferpool;std::lock_guard<std::mutex> lock_guard(bufferpool_set_mutex);bufferpool_set_t::iterator it = bufferpool_set.find(buf_size);if (it == bufferpool_set.end ()){bufferpool = new bufferpool_t(buf_size);bool rc = bufferpool_set.insert (bufferpool_set_t::value_type(buf_size,bufferpool)).second;assert(rc);}else{bufferpool = it->second;}buf =(void*) bufferpool->alloc_buffer ();}else{buf = internal_malloc(size_);}return buf;}bool mempool_t::free( void* ptr ){uint32_t data_size;bool rc = bufferpool_t::get_buffer_size ((char*)ptr,data_size);if (rc){std::lock_guard<std::mutex> lock_guard(bufferpool_set_mutex);bufferpool_t *bufferpool;bufferpool_set_t::iterator it = bufferpool_set.find(data_size);if (it == bufferpool_set.end ()){assert(false);}bufferpool = it->second;return bufferpool->free_buffer ((char*)ptr);;}else{return internal_free (ptr);}return false;}bool mempool_t::internal_free( void* ptr_){char *buf = (char*)ptr_ - sizeof(uint32_t);uint32_t size = *(uint32_t*)buf;if (size > max_alloc_size){uint32_t tail_size = *(uint32_t*)((char*)ptr_ + size);if (tail_size == size){delete buf;return true;}}return false;}bool mempool_t::get_bufferpool_size( uint32_t size_, uint32_t &buf_size_ ){if (size_ > max_alloc_size) {return false;}/*求整数的最接近2的幂,向上对齐*/size_ = size_ - 1;size_ = size_ | (size_ >> 1);size_ = size_ | (size_ >> 2);size_ = size_ | (size_ >> 4);size_ = size_ | (size_ >> 8);size_ = size_ | (size_ >>16);size_ = size_ + 1;/*判断是否是2的幂*/if(0 != (size_&(size_-1))){assert(false);}buf_size_ = size_;return true;}void * mempool_t::internal_malloc( const uint32_t &size_ ){uint32_t buf_size = size_ + sizeof(uint32_t)*2;void *buf = malloc (buf_size);*(uint32_t*)buf = size_;*(uint32_t*)((char*)buf + sizeof(uint32_t)+size_) = size_;return ((char*)buf+sizeof(uint32_t));}void mempool_t::config( const uint32_t &max_buffer_size_ ){max_alloc_size = max_buffer_size_;}
classbufferpool_t

#include "buffer_t.hpp"class bufferpool_t{public:bufferpool_t(const uint32_t &buffer_size_,const uint32_t &limit_size_ = 20);~bufferpool_t(void); char *alloc_buffer(); bool free_buffer(char *buffer_); static bool get_buffer_size(char *buffer_, uint32_t &buffer_size_);private:typedef std::list<buffer_t*> buffer_list_t;buffer_list_t buffer_list;//buffer 类型大小,一个bufferpool_t只管理//同样大小的内存uint32_t buffer_type_size;//空闲内存最大数量uint32_t limit_buffer_list_size;//获取内存次数uint32_t alloc_times;//释放内存次数uint32_t free_times;};
#include "stdafx.h"#include "bufferpool_t.h"bufferpool_t::bufferpool_t(const uint32_t &buffer_size_,const uint32_t &limit_size_){buffer_type_size = buffer_size_;limit_buffer_list_size = limit_size_;free_times = 0;alloc_times = 0;}bufferpool_t::~bufferpool_t(void){buffer_t *buffer;while (buffer_list.empty () == false){buffer = buffer_list.front ();buffer_list.pop_back ();buffer->relase_buffer();}}char * bufferpool_t::alloc_buffer(){buffer_t *buffer;char *buf;if (buffer_list.empty ()){char *buf = new char[buffer_type_size+sizeof(buffer_t)];buffer = new (buf)buffer_t(buffer_type_size,buf);//添加成员}else{buffer = buffer_list.front ();buffer_list.pop_front ();}++alloc_times ;buf = buffer->buf ();buffer->use (true);return buf;}bool bufferpool_t::free_buffer( char * buffer_){buffer_t *buffer = (buffer_t*)(buffer_ - sizeof(buffer_t));if (buffer->check_code () &&  buffer->length () == buffer_type_size){if(buffer_list.size () < limit_buffer_list_size){buffer->use (false);buffer_list.push_back (buffer);++free_times;return true;}else{buffer->relase_buffer();return true;}}return false;}bool bufferpool_t::get_buffer_size( char *buffer_ ,uint32_t &buffer_size_){buffer_t *buffer = (buffer_t*)(buffer_ - sizeof(buffer_t));if (buffer->check_code () &&buffer->use()&&buffer->buf () == buffer_){buffer_size_ = buffer->length ();return true;}else{return false;}}
class buffer_t

#pragma once#include "stddef.hpp"class buffer_t{public:inline buffer_t(uint32_t length_, char *data_buf_){buf_code = 0xbeaf;buf_length = length_;buf_data = data_buf_;}inline void relase_buffer(void){delete []buf_data;}inline bool check_code(){return buf_code == 0xbeaf;}inline char *buf(){return buf_data+sizeof(*this);}inline uint32_t length(){return buf_length;}inline bool use(){return is_use;}inline void use(const bool &is_use_){is_use = is_use_;}private:char *buf_data;bool is_use;uint32_t buf_code;uint32_t buf_length;};
写的不好的地方,请指出

0 0