内存池代码如下:
#ifndef POOL_H_INCLUDED_GF
#define POOL_H_INCLUDED_GF
//
// 大块内存分配器
//
#ifdef _WIN32
#pragma warning(push)
#pragma warning(disable : 4018) // signed/unsigned mismatch
#pragma warning(disable : 4290) // exception spec ignored
#endif
#include <exception>
#include <list>
#include <algorithm>
#include <iostream>
#include <cassert>
#define TYPE_CAST(DstType, SrcData) reinterpret_cast<DstType>(SrcData)
// 数据块节点,形成链表
struct SBlockHead
{
SBlockHead* poPrev; // prev指针
SBlockHead* poNext; // next指针
size_t nSize; // 块大小
int nFree; // 剩余数量
SBlockHead(SBlockHead* prev, SBlockHead* next, size_t size, int free) :
poPrev(prev), poNext(next), nSize(size), nFree(free)
{
}
~SBlockHead()
{
}
};
class CChunkPool
{
struct SKiller
{
void operator()(char *p)
{
delete [] p;
}
};
enum Pool_Const
{
MEM_INIT_SIZE = 0xfffff,
MEM_MIN_SIZE = 0xf,
BLOCK_SZIE = sizeof(SBlockHead),
};
enum Block_Use
{
BLOCK_USE = 0, BLOCK_UNUSE = 1,
};
public:
// 分配内存,并注册到系统中去
CChunkPool(size_t size = MEM_INIT_SIZE) : m_nSize(size)
{
if((m_nSize - BLOCK_SZIE) < MEM_MIN_SIZE)
{
assert(false);
}
char* poBlock = new char[m_nSize];
if (!poBlock)
{
throw std::bad_alloc();
}
m_listMemPool.push_back(poBlock);
m_poMemBlocks = (SBlockHead*)poBlock;
m_poMemBlocks->poPrev = 0;
m_poMemBlocks->poNext = 0;
m_poMemBlocks->nFree = BLOCK_UNUSE;
m_poMemBlocks->nSize = (m_nSize - BLOCK_SZIE);
}
~CChunkPool()
{
std::for_each(m_listMemPool.begin(), m_listMemPool.end(), SKiller());
}
public:
// 分配size大小的内存,跟具体的对象无关
void* allocate(size_t size)
{
if(size > (m_nSize - BLOCK_SZIE))
{
throw std::bad_alloc();
}
// 如果没有足够的空间,就首先分配空间
SBlockHead* poBlock = m_poMemBlocks;
while (1)
{
while (BLOCK_USE == poBlock->nFree)
{
if(0 == poBlock->poNext)
{
__Buy(poBlock);
}
poBlock = poBlock->poNext;
}
if(poBlock->nSize < size)
{
if (0 == poBlock->poNext)
{
__Buy(poBlock);
}
else
{
poBlock = poBlock->poNext;
}
continue;
}
break;
}
// 剩余的内存不足一个SBlockHead, 就直接全部返回
if(poBlock->nSize - size < 2 * BLOCK_SZIE)
{
poBlock->nFree = BLOCK_USE;
return TYPE_CAST(char*, poBlock) + BLOCK_SZIE;
}
else
{
// 把剩余的内存保存起来
SBlockHead * poLeftBlock = (SBlockHead*)(TYPE_CAST(char*, poBlock) + size + BLOCK_SZIE);
assert(poLeftBlock);
if(poBlock->poNext)
{
poBlock->poNext->poPrev = poLeftBlock;
}
poLeftBlock->poNext = poBlock->poNext;
poBlock->poNext = poLeftBlock;
poLeftBlock->poPrev = poBlock;
poBlock->nFree = BLOCK_USE;
poLeftBlock->nSize = poBlock->nSize - size - BLOCK_SZIE;
poBlock->nSize = size;
poLeftBlock->nFree = BLOCK_UNUSE;
return TYPE_CAST(char*, poBlock) + BLOCK_SZIE;
}
}
// 释放内存,poMem是从allocate函数中分配的
void deallocate(void* poMem, size_t nSize = 0)
{
if(!poMem)
{
return;
}
// 得到原来的SBlockHead*
SBlockHead* poBlock = TYPE_CAST(SBlockHead*, (static_cast<char*>(poMem) - BLOCK_SZIE));
// 既有前节点,又有后节点,下同
if(poBlock->poPrev && poBlock->poNext)
{
if(poBlock->poPrev->nFree && poBlock->poNext->nFree)
{
poBlock->poPrev->nSize += poBlock->nSize + poBlock->poNext->nSize + 2 * BLOCK_SZIE;
poBlock->poPrev->poNext = poBlock->poNext->poNext;
if(poBlock->poNext->poNext)
{
poBlock->poNext->poNext->poPrev = poBlock->poPrev;
}
return;
}
}
if(poBlock->poPrev)
{
if(poBlock->poPrev->nFree)
{
poBlock->poPrev->nSize += (poBlock->nSize + BLOCK_SZIE);
poBlock->poPrev->poNext = poBlock->poNext;
if(poBlock->poNext)
{
poBlock->poNext->poPrev = poBlock->poPrev;
}
poBlock->nFree= BLOCK_UNUSE;
return;
}
}
if(poBlock->poNext)
{
if(poBlock->poNext->nFree)
{
poBlock->nSize += (poBlock->poNext->nSize + BLOCK_SZIE);
poBlock->poNext = poBlock->poNext->poNext;
if(poBlock->poNext)
{
poBlock->poNext->poPrev = poBlock;
}
poBlock->nFree = BLOCK_UNUSE;
return;
}
}
poBlock->nFree = BLOCK_UNUSE;
}
// 显示内存使用情况
void dump()
{
using namespace std;
SBlockHead *b = m_poMemBlocks;
while(1)
{
cout << "Size=" << b->nSize << ", free=" << b->nFree <<
", prev=" << b->poPrev << ", next=" << b->poNext << endl;
if(b->poNext)
{
b = b->poNext;
}
else
{
break;
}
}
}
protected:
// 增长内存一块m_nSize的内存,并加入到poOldBlock后面
void __Buy(SBlockHead* poOldBlock)
{
char* poNewMem = new char[m_nSize];
if (!poNewMem)
{
throw std::bad_alloc();
}
m_listMemPool.push_back(poNewMem);
SBlockHead* poNewBlock = TYPE_CAST(SBlockHead*, poNewMem);
poNewBlock->poPrev = poOldBlock;
poNewBlock->poNext = 0;
poNewBlock->nFree = BLOCK_UNUSE;
poNewBlock->nSize = (m_nSize - BLOCK_SZIE);
poOldBlock->poNext = poNewBlock;
}
private:
size_t m_nSize;
std::list<char *> m_listMemPool;
SBlockHead* m_poMemBlocks;
};
#ifdef _WIN32
#pragma warning(pop)
#endif
#endif
stl allocator 代码如下:
#ifndef __STL_ALLOCATOR_H__
#define __STL_ALLOCATOR_H__
//
// 大块动态allocator,可以用于STL容器的分配器
//
#include "dynamicmempool.h"
// 申明
template <typename T> class CDynamicAllocator;
// 偏特化void
template <> class CDynamicAllocator<void>
{
public:
typedef void* pointer;
typedef const void* const_pointer;
typedef void value_type;
template <class U>
struct rebind { typedef CDynamicAllocator<U> other; };
};
// Allocator definition
template <typename T>
class CDynamicAllocator
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
template <class U>
struct rebind
{
typedef CDynamicAllocator<U> other;
};
CDynamicAllocator() {}
template <class U> CDynamicAllocator(const CDynamicAllocator<U>&){}
public:
pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) const { return &x; }
// 分配函数
pointer allocate(size_type size, const_pointer hint = 0)
{
return static_cast<pointer>(m_oMemPool.allocate(size * sizeof(T)));
}
// 释放内存
void deallocate(pointer p, size_type n)
{
m_oMemPool.deallocate(p, n);
}
void deallocate(void* p, size_type n)
{
m_oMemPool.deallocate(p, n);
}
size_type max_size() const throw()
{
return size_t(-1) / sizeof(value_type);
}
void construct(pointer p, const T& val)
{
new(static_cast<void*>(p)) T(val);
}
void construct(pointer p)
{
new(static_cast<void*>(p)) T();
}
void destroy(pointer p) { p->~T(); }
private:
static CChunkPool m_oMemPool;
};
template <class T>
CChunkPool CDynamicAllocator<T>::m_oMemPool;
#endif
测试代码如下:
// test.cpp : 定义控制台应用程序的入口点。.
//
#include "stdafx.h"
#include <iostream>
#include "dynamicallocator.h"
#include <time.h>
#include <vector>
using namespace std;
struct SInfo
{
int nA;
int nB;
SInfo() : nA(0), nB(0)
{
}
SInfo(int i, int j) : nA(i), nB(j)
{
}
~SInfo()
{
}
};
int _tmain(int argc, _TCHAR* argv[])
{
vector<SInfo, CDynamicAllocator<SInfo> > vecInt;
clock_t now = clock();
for (int j = 0; j < 10000; j++)
{
for (int i = 0; i < 0xffff / 4; i++)
{
vecInt.push_back(SInfo(i, 0));
}
vecInt.clear();
}
clock_t end = clock();
int n = end - now;
return 0;
}