完整的stl allocator代码及其测试

    技术2024-08-23  137

    内存池代码如下:

     

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

     

     

     

     

     

     

    最新回复(0)