您的位置:首页 > 编程语言

完整的stl allocator代码及其测试

2011-02-05 22:30 204 查看
内存池代码如下:

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: