内存池代码如下:
#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;
// 偏特化voidtemplate <> 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 definitiontemplate <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;}