完整的stl allocator代码及其测试

内存池代码如下:

 

#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;
}

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值