5D空间

学习总结与经验交流

   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  对象池的指针版本。池中本质上是一群对象,只构造一次,返回指针。主要支持频繁重建的内存空间不连续的自建结构,如树,链表。
/******************************************************************
 *名称:PointerPool(指针池)(模板)
 *版本号:0.1
 *作者:赵耀(中山大学2010级)
 *时间:2011.4.11
 *简介:
 *        对应于对象池,这是一个指针池,用于缓存频繁调用的指针(对象).主要支
 *    持频繁重建的树或链表等结构.具有默认构造函数接收一个size_t对象表明指针
 *    分块的大小,默认为10.接收的参数如果<=0则会抛出异常invalid_argument.
 *    public方法:
 *        T* getPointer(); 从池中返回一个该类型对象的指针;
 *        void recyclePointer( T* ); 接受需要回收的指针;
 *        void clear(); 清空池以释放占用的内存;
 *        bool empty(); 返回池是否为空;
 *        size_t size(); 返回池中总指针数量;
 *        size_t remain(); 返回指针池剩余可用指针的数量;
 *    注意:
 *        使用方法可简单地想成通过两个成员函数来代替new和delete.必须确保分
 *    配的指针得到回收!必须确保回收的指针不是外来指针!因为未进行二次初始化,
 *    重新分配得到的指针所指对象可能是上一次使用后的残余对象,请进行必要的初
 *    话工作.
 *
 *未完成特性:
 *        因为主要支持树,链表等内存空间不连续的结构,所以未实现成数组规模
 *    地分配指针的功能.
 *
 *已知bug:暂无
 *
 *版权信息:
 *        该代码为开源代码,原作者保留其所有权.你可以拷贝,修改,使用该代码,但
 *    是请保留必要的版权信息.
*****************************************************************
*/

#ifndef POINTERPOOL_H
#define POINTERPOOL_H

#include 
<vector>
#include 
<queue>
#include 
<stdexcept>
#include 
<memory>
using namespace std;

template
< typename T >
class PointerPool
{
public:
    
//Create a PointerPool to contain size pointers.
    PointerPool( size_t size = kDefaultChunkSize )
        
throw ( invalid_argument, bad_alloc );
    
~PointerPool();

    
//Return a specific pointer to client.
    T *getPointer();
    
//Recycle the pointer that the client doesn't need any more.
    void recyclePointer( T* );
    
//Clear the pool and release the memory.
    void clear();
    
bool empty();
    
//Return the total number of pointers the pool contains.
    size_t size();
    
//Return the number of pointers remain available.
    size_t remain();

protected:
    queue
< T* > mFreeList;
    vector
< T* > mAllpointers;//A record of all pointers which help
    
//to destroy them.

    size_t mChunkSize;
    
static const size_t kDefaultChunkSize = 10;

    
//Allocate mChunkSize new pointers and add them to the
    
//mFreeList.
    void allocateChunk();
    
//help the destructor the delete the pointers int the pool.
    static void deleteHelper( T* );

private:
    
//Hide the copy constructor and assignment symbol.
    PointerPool( const PointerPool< T > & );
    PointerPool
< T > &operator=const PointerPool< T > & );
}
;

template
< typename T >
size_t PointerPool
<T>::remain()
{
    
return mFreeList.size();
}


template
< typename T >
bool PointerPool<T>::empty()
{
    
return remain() == 0;
}


template
< typename T >
size_t PointerPool
<T>::size()
{
    
return mChunkSize * mAllpointers.size();
}


template
< typename T >
PointerPool
<T>::PointerPool( size_t size /*= kDefaultChunkSize */ ) throw ( invalid_argument, bad_alloc )
{
    
if ( size <= 0 )
        
throw invalid_argument( "chunk size must be positive" );

    mChunkSize 
= size;
    allocateChunk();
}


template
< typename T >
*PointerPool<T>::getPointer()
{
    
if ( mFreeList.empty() )
        allocateChunk();

    T 
*ptr = mFreeList.front();
    mFreeList.pop();
    
return ptr;
}


template
< typename T >
void PointerPool<T>::clear()
{
    for_each( mAllpointers.begin(), mAllpointers.end(), deleteHelper );

    mAllpointers.clear();
    
while ( !mFreeList.empty() )
        mFreeList.pop();
}


template
< typename T >
void PointerPool<T>::recyclePointer( T *ptr )
{
    mFreeList.push( ptr );
}


template
< typename T >
void PointerPool<T>::allocateChunk()
{
    T
* newPointerChunk = new T[ mChunkSize ];

    mAllpointers.push_back( newPointerChunk );
    
for ( int i = 0; i < mChunkSize; i++ )
    
{
        mFreeList.push( 
&newPointerChunk[i] );
    }

}


template
< typename T >
void PointerPool<T>::deleteHelper( T *pointerChunk )
{
    delete [] pointerChunk;
}


template
< typename T >
PointerPool
<T>::~PointerPool()
{
    for_each( mAllpointers.begin(), mAllpointers.end(), deleteHelper );
}


#endif

以下为测试代码:
#include "PointerPool.h"
#include 
<iostream>
using namespace std;

class ListNode
{
public:
    
int value;
    ListNode 
*nextPtr;

    ListNode() : value(
0), nextPtr(0)
    
{}
}
;

int growing()
{
    
static int numGrouwing = 0;
    
return numGrouwing++;
}


int main()
{
    
const int cases = 2;
    PointerPool
< ListNode > lnPool;

    
//Make 2 tests.
    for ( int i = 0; i < cases; i++ )
    
{
        
if ( lnPool.empty() )
            cout 
<< "The pool is empty!" << endl;
        
else
            cout 
<< "The pool has " << lnPool.remain()
            
<< " pointers available" << endl;

        
//Create the head of a list.
        ListNode *start = lnPool.getPointer();
        start
->value = growing();
        ListNode 
*last = start;

        
//Complete the list with length of 100.
        for ( int j = 1; j < 100; j++ )
        
{
            ListNode 
*tmp = lnPool.getPointer();
            tmp
->value = growing();
            last
->nextPtr = tmp;
            last 
= tmp;
        }


        
//Travel and cout the value of each node.
        ListNode *current = start;
        
while ( current != 0 )
        
{
            cout 
<< current->value << '\t';
            current 
= current->nextPtr;
        }


        
//Recycle all pointers back to the pool.
        while ( start != 0 )
        
{
            current 
= start;
            start 
= start->nextPtr;
            lnPool.recyclePointer( current );
        }


        cout 
<< "The pool has " << lnPool.size() << " pointers"
            
<< "\n\n";
        
//Try clear the pool
        lnPool.clear();
    }

}
posted on 2011-04-11 16:13 今晚打老虎 阅读(1827) 评论(5)  编辑 收藏 引用 所属分类: 我的开源库

评论

# re: PointerPool(指针池) 2011-04-11 18:26 ooseven
本质上就是一个ptrvector吧?  回复  更多评论
  

# re: PointerPool(指针池) 2011-04-11 18:49 bennycen
。。。。。。。。。  回复  更多评论
  

# re: PointerPool(指针池) 2011-04-11 20:42 千暮(zblc)
测试了下,如果把链表长度改为1w,kDefaultChunkSize长度改为100,注释掉所有输出,cases改为2w 比不用你的指针池而直接new快4-5倍.

  回复  更多评论
  

# re: PointerPool(指针池) 2011-04-12 00:19 今晚打老虎
@千暮(zblc)
感谢测试。其实我还在c++的摸爬滚打中,对性能测试的概念还比较模糊,也没有学习和体验过系统的测试。希望能得到有关方面的指教,比如,测试工具需要什么么?参考指标有哪些?  回复  更多评论
  

# re: PointerPool(指针池) 2011-04-12 00:46 千暮(zblc)
@今晚打老虎
其实不用考虑得太复杂 就是计算时间(在代码中插入时钟计算间隔)、空间消耗(重载分配堆内存的内置函数)和运行效率的稳定性(代码运行的边界情况进行分析)。至于系统测试,也只是把情况划分得更加细致而已。  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理