一个分配固定大小块的内存池(memory pool) 的例子 FROM POCO

//
// MemoryPool.h
//
// $Id: //poco/1.4/Foundation/include/Poco/MemoryPool.h#1 $
//
// Library: Foundation
// Package: Core
// Module:  MemoryPool
//
// Definition of the MemoryPool class.
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//

 

/*
//z 2011-06-23 15:13:07@is2120.CSDN 转载请注明出处
设计思想:
比较简单,申请若干个(128)固定大小的内存块,
将各内存块指针存放在vector中,申请则出vector,释放则回收到vec中去。
*/

#ifndef Foundation_MemoryPool_INCLUDED
#define Foundation_MemoryPool_INCLUDED


#include  "Poco/Foundation.h"
#include  "Poco/Mutex.h"
#include  <vector>
#include  <cstddef>


namespace  Poco {

/*
14:01 2011-6-23
一个固定大小内存块的pool
这个class的主要目的是加速内存分配
同时在相同大小的块一遍又一遍分配时避免了内存碎片
*/

class  Foundation_API MemoryPool
  /// A simple pool for fixed-size memory blocks.
  ///
  /// The main purpose of this class is to speed-up
  /// memory allocations, as well as to reduce memory
  /// fragmentation in situations where the same blocks
  /// are allocated all over again, such as in server
  /// applications.
  ///
  /// All allocated blocks are retained for future use.
  /// A limit on the number of blocks can be specified.
  /// Blocks can be preallocated.
{
public :
  MemoryPool(std::size_t  blockSize, int  preAlloc = 0int  maxAlloc = 0 );
    //z@is2120 14:03 2011-6-23
    //z 使用给定的blocksize创建一个memorypool。
    //z 预分配的大小由preAlloc指定
    /// Creates a MemoryPool for blocks with the given blockSize.
    /// The number of blocks given in preAlloc are preallocated.
    
  ~MemoryPool();

  //z 从memory pool中得到一个block
  void * get();
    /// Returns a memory block. If there are no more blocks
    /// in the pool, a new block will be allocated.
    ///
    /// If maxAlloc blocks are already allocated, an
    /// OutOfMemoryException is thrown.

  //z 将一个 memory block 返回到pool中去。
  void  release(void * ptr);
    /// Releases a memory block and returns it to the pool.

  //z 返回 block size
  std::size_t  blockSize() const ;
    /// Returns the block size.
  
  //z 返回已分配的 blocks 的数目
  int  allocated() const ;
    /// Returns the number of allocated blocks.
    
  //z 返回在pool中可用的块数目
  int  available() const ;
    /// Returns the number of available blocks in the pool.

private :
  //z 禁用了默认构造函数;拷贝构造函数以及赋值构造函数
  MemoryPool();
  MemoryPool(const  MemoryPool&);
  MemoryPool& operator  = (const  MemoryPool&);
  
  //z 保留128的block
  enum
  {
    BLOCK_RESERVE = 128
  };
  
  //z 使用了vector来保存block的地址
  typedef  std::vector<char *> BlockVec;
  
  //z 块大小
  std::size_t  _blockSize;
  //z 允许的最大块数目
  int          _maxAlloc;
  //z 已分配
  int          _allocated;
  //z 存储块地址的容器
  BlockVec    _blocks;
  //z 互斥
  FastMutex   _mutex;
};


//
// inlines
//
//z 返回块大小
inline  std::size_t  MemoryPool::blockSize() const
{
  return  _blockSize;
}

//z 返回总的分配的数目
inline  int  MemoryPool::allocated() const
{
  return  _allocated;
}

//z 凡存在blocks中的都是未交付使用的(但已分配)
inline  int  MemoryPool::available() const
{
  return  (int ) _blocks.size();
}


// namespace Poco


#endif  // Foundation_MemoryPool_INCLUDED

 

#include  "Poco/MemoryPool.h"
#include  "Poco/Exception.h"

namespace  Poco {


MemoryPool::MemoryPool(std::size_t  blockSize, int  preAlloc, int  maxAlloc):
  _blockSize(blockSize),
  _maxAlloc(maxAlloc),
  _allocated(preAlloc)
{
  poco_assert (maxAlloc == 0  || maxAlloc >= preAlloc);
  poco_assert (preAlloc >= 0  && maxAlloc >= 0 );

  int  r = BLOCK_RESERVE;
  if  (preAlloc > r)
    r = preAlloc;
  if  (maxAlloc > 0  && maxAlloc < r)
    r = maxAlloc;
  
  //z vector 保留r空间
  _blocks.reserve(r);
  
  for  (int  i = 0 ; i < preAlloc; ++i)
  {
    //z 直接分配;此时会不会出现异常?
    _blocks.push_back(new  char [_blockSize]);
  }
}

MemoryPool::~MemoryPool()
{
  //z 所有的都放在blockvec中
  for  (BlockVec::iterator it = _blocks.begin(); it != _blocks.end(); ++it)
  {
    delete  [] *it;
  }
}


void * MemoryPool::get()
{
  FastMutex::ScopedLock lock(_mutex);
  
  if  (_blocks.empty())
  {
    if  (_maxAlloc == 0  || _allocated < _maxAlloc)
    {
      ++_allocated;
      return  new  char [_blockSize];
    }
    else  throw  OutOfMemoryException("MemoryPool exhausted" );
  }
  else
  {
    //z 从尾端取出一个
    char * ptr = _blocks.back();
    //z 从尾端弹出
    _blocks.pop_back();
    return  ptr;
  }
}

  
void  MemoryPool::release(void * ptr)
{
  FastMutex::ScopedLock lock(_mutex);
  
  //z 将get的内存还回vec中去。
  _blocks.push_back(reinterpret_cast <char *>(ptr));
}


// namespace Poco

posted @ 2011-06-23 15:17  BiG5  阅读(420)  评论(0编辑  收藏  举报