有了前面的内存块和线程锁,现在就可以写内存池了,关于内存池的原理、好处什么的,这里都一概不说了,主要就是把自己封装的东西来贴出来分享,有些模块我经常用,感觉还是比较干净利索,假若您发现了其中的bug或者不合理的地方,请发个评论,一块讨论下,就怕自己成了井底之蛙,这些可能都有一些成熟的第三方库了,但自己总喜欢造自己的轮子,就是一兴趣吧!
这里的内存池和内存块不同的地方就是内存池将内存块组成一个链表来管理,动态的来控制这个链表的个数,如果不停的调用Malloc来申请Node,链表的长度就会很长。其中有个链表指针(mem_block_header_free)指向最前面可以申请Node的的内存块,每次Free一个Node时就检查这个Node所在的内存块是否在mem_block_header_free的前面,若在前面就赋值给它,另外还有一个变量free_sustained,它负责记录连续Free的次数,若连续Free的次数等于一个内存块的Node数量就检查下是否有可以释放的内存块,以此来减少内存块链表的长度,此外通过模板参数来支持线程安全。
在使用时,模板参数要根据自己的情况来定义,当然要熟悉使用还是要理解下内部的原理,内部总共就四个有效变量,不涉及什么算法,理解起来不算困难,另外我还写了一个基于对象的内存池,对象大小本身就是固定大小的,所以很好实现,能调用对象的构造和析构函数,以后再发吧,下面就把本次的代码贴出来:
注:
CSDN编辑博客的工具真难用,表示强烈的鄙视下
/*
============================================================================================
内存池模块 固定长度的内存池
通过模板参数来做线程安全
add 2013.11.22 by yuwf
Copyright (c), ...
=============================================================================================
*/
#ifndef _PALANTIR_MEM_POOL_H
#define _PALANTIR_MEM_POOL_H
#include "PLTLocker.h"
#include "PLTMemBlock.h"
#include "PLTMemBlock2.h"
namespace Palantir
{
template < unsigned int _NODE_SIZE_, unsigned int _BLOCK_NODE_COUNT_ = 8, class _LOCK_TYPE_ = EmptyLocker, class _BLOCK_TYPE_ = MemBlock2<_NODE_SIZE_,_BLOCK_NODE_COUNT_> >
class MemPool
{
public:
// 内存块 组织成链表
class MemBlock : public _BLOCK_TYPE_
{
public:
MemBlock() : pnext(nullptr) {}
MemBlock* pnext;
};
typedef _LOCK_TYPE_ Locker; // 锁类型
typedef LockerGuard<_LOCK_TYPE_> AutoLocker; // 辅助使用
public:
// 构造和析构函数
MemPool();
virtual ~MemPool();
// 分配一块内存
inline void* Malloc();
// p 必须是从malloc获取的
// 返回值表示是否删除成功
inline bool Free(const void* p);
// 将所有分配的内存回收到内存池中
// 没有使用的内存块回收给系统
inline void Free();
// 将所有分配的内存回收到系统
inline void Destroy();
// 内存池交换
inline void Swap( MemPool& pool );
// 获取当前的block的数量
inline unsigned int Block_Count();
// 获取这个内存池占用内存的大小
inline unsigned int Mem_Size();
protected:
// 释放掉没有使用的block 将内存回收到系统中
void _Destroy_NotUse_Block();
MemBlock* mem_block_header; // 记录第一个block的位置
MemBlock* mem_block_header_free; // 记录最前面有空的block 如果这个block也没空就要重新申请一个block
unsigned int free_sustained; // 连续回收的次数 有分配就回归0
Locker locker; // 线程池的锁
};
// 功能实现部分 ========================
template <unsigned int _NODE_SIZE_, unsigned int _BLOCK_NODE_COUNT_, class _LOCK_TYPE_, class _BLOCK_TYPE_>
MemPool<_NODE_SIZE_,_BLOCK_NODE_COUNT_,_LOCK_TYPE_,_BLOCK_TYPE_>::MemPool() : mem_block_header(nullptr), mem_block_header_free(nullptr), free_sustained(0)
{
}
template <unsigned int _NODE_SIZE_, unsigned int _BLOCK_NODE_COUNT_, class _LOCK_TYPE_, class _BLOCK_TYPE_>
MemPool<_NODE_SIZE_,_BLOCK_NODE_COUNT_,_LOCK_TYPE_,_BLOCK_TYPE_>::~MemPool()
{
// 将内存回收给系统
Destroy();
}
template <unsigned int _NODE_SIZE_, unsigned int _BLOCK_NODE_COUNT_, class _LOCK_TYPE_, class _BLOCK_TYPE_>
inline void* MemPool<_NODE_SIZE_,_BLOCK_NODE_COUNT_,_LOCK_TYPE_,_BLOCK_TYPE_>::Malloc()
{
AutoLocker lock( locker );
free_sustained = 0;
if ( mem_block_header == nullptr )
{
mem_block_header = new MemBlock;
mem_block_header_free = mem_block_header;
}
MemBlock* free_block = mem_block_header_free;
while( free_block->Is_Full() )
{
if ( free_block->pnext == nullptr )
{
free_block->pnext = new MemBlock;
mem_block_header_free = free_block->pnext;
break;
}
free_block = free_block->pnext;
}
return free_block->Malloc();
}
template <unsigned int _NODE_SIZE_, unsigned int _BLOCK_NODE_COUNT_, class _LOCK_TYPE_, class _BLOCK_TYPE_>
inline bool MemPool<_NODE_SIZE_,_BLOCK_NODE_COUNT_,_LOCK_TYPE_,_BLOCK_TYPE_>::Free(const void* p)
{
if ( p )
{
AutoLocker lock( locker );
MemBlock* at_block = mem_block_header;
bool free_at_back = true; // 判断p所在的block是否在mem_block_header_free的后面
// 遍历block 找到p所在的block
while( at_block )
{
if ( at_block == mem_block_header_free )
{
free_at_back = false;
}
if ( at_block->Is_From(p) )
{
break;
}
at_block = at_block->pnext;
}
if ( !at_block )
{
return false;
}
// 如果p所在的block是在mem_block_header_free的前面
// 将这个block赋值给mem_block_header_free 因为他记录最靠前可能有空的block
if ( free_at_back )
{
mem_block_header_free = at_block;
}
++free_sustained;
at_block->Free(p);
if ( free_sustained % MemBlock::NODE_COUNT == 0 )
{
_Destroy_NotUse_Block();
}
return true;
}
return false;
}
template <unsigned int _NODE_SIZE_, unsigned int _BLOCK_NODE_COUNT_, class _LOCK_TYPE_, class _BLOCK_TYPE_>
inline void MemPool<_NODE_SIZE_,_BLOCK_NODE_COUNT_,_LOCK_TYPE_,_BLOCK_TYPE_>::Free()
{
AutoLocker lock( locker );
MemBlock* cur_block = mem_block_header;
MemBlock* last_block = nullptr;
while( cur_block )
{
// 发现这个block没有使用 归还给系统
if ( cur_block->Is_Not_Use() )
{
if ( last_block )
{
last_block->pnext = cur_block->pnext;
}
if ( cur_block == mem_block_header )
{
mem_block_header = cur_block->pnext;
}
MemBlock* mem = cur_block;
cur_block = cur_block->pnext;
delete mem;
}
else
{
cur_block->Free();
last_block = cur_block;
cur_block = cur_block->pnext;
}
}
mem_block_header_free = mem_block_header;
free_sustained = 0;
}
template <unsigned int _NODE_SIZE_, unsigned int _BLOCK_NODE_COUNT_, class _LOCK_TYPE_, class _BLOCK_TYPE_>
inline void MemPool<_NODE_SIZE_,_BLOCK_NODE_COUNT_,_LOCK_TYPE_,_BLOCK_TYPE_>::Destroy()
{
AutoLocker lock( locker );
MemBlock* cur_block = mem_block_header;
while( cur_block )
{
MemBlock* mem = cur_block;
mem->Free();
cur_block = cur_block->pnext;
delete mem;
}
mem_block_header = nullptr;
mem_block_header_free = nullptr;
free_sustained = 0;
}
template <unsigned int _NODE_SIZE_, unsigned int _BLOCK_NODE_COUNT_, class _LOCK_TYPE_, class _BLOCK_TYPE_>
inline void MemPool<_NODE_SIZE_,_BLOCK_NODE_COUNT_,_LOCK_TYPE_,_BLOCK_TYPE_>::Swap( MemPool& pool )
{
AutoLocker lock( locker );
AutoLocker lock2( pool.locker );
MemBlock* ptemp = mem_block_header;
mem_block_header = pool.mem_block_header;
pool.mem_block_header = ptemp;
ptemp = mem_block_header_free;
mem_block_header_free = pool.mem_block_header_free;
pool.mem_block_header_free = ptemp;
unsigned int itemp = free_sustained;
free_sustained = pool.free_sustained;
pool.free_sustained = itemp;
}
template <unsigned int _NODE_SIZE_, unsigned int _BLOCK_NODE_COUNT_, class _LOCK_TYPE_, class _BLOCK_TYPE_>
inline unsigned int MemPool<_NODE_SIZE_,_BLOCK_NODE_COUNT_,_LOCK_TYPE_,_BLOCK_TYPE_>::Block_Count()
{
AutoLocker lock( locker );
unsigned int count = 0;
MemBlock* cur_block = mem_block_header;
while( cur_block )
{
MemBlock* mem = cur_block;
cur_block = cur_block->pnext;
++count;
}
return count;
}
template <unsigned int _NODE_SIZE_, unsigned int _BLOCK_NODE_COUNT_, class _LOCK_TYPE_, class _BLOCK_TYPE_>
inline unsigned int MemPool<_NODE_SIZE_,_BLOCK_NODE_COUNT_,_LOCK_TYPE_,_BLOCK_TYPE_>::Mem_Size()
{
return Block_Count() * sizeof(MemBlock) + sizeof(*this);
}
template <unsigned int _NODE_SIZE_, unsigned int _BLOCK_NODE_COUNT_, class _LOCK_TYPE_, class _BLOCK_TYPE_>
inline void MemPool<_NODE_SIZE_,_BLOCK_NODE_COUNT_,_LOCK_TYPE_,_BLOCK_TYPE_>::_Destroy_NotUse_Block()
{
MemBlock* cur_block = mem_block_header;
MemBlock* last_block = nullptr;
while( cur_block )
{
// 发现这个block没有使用 归还给系统
if ( cur_block->Is_Not_Use() )
{
if ( last_block )
{
last_block->pnext = cur_block->pnext;
}
if ( cur_block == mem_block_header )
{
mem_block_header = cur_block->pnext;
}
if ( mem_block_header_free == cur_block )
{
mem_block_header_free = cur_block->pnext;
}
MemBlock* mem = cur_block;
cur_block = cur_block->pnext;
delete mem;
}
else
{
last_block = cur_block;
cur_block = cur_block->pnext;
}
}
}
}
#endif