游戏开发论坛

 找回密码
 立即注册
搜索
查看: 3078|回复: 9

小弟精心打造的一个对象缓冲器,可支持任何类型的对象

[复制链接]

45

主题

157

帖子

169

积分

注册会员

Rank: 2

积分
169
QQ
发表于 2009-3-6 09:20:00 | 显示全部楼层 |阅读模式

设计思路:

  以页面为单位预先分配一定数量的对象给客户程序使用,用完再归还回来。
  
  采用页面链表技术,理论上分配数量无上限。
  
  页面中的对象用堆管理,请求时从堆顶移出一个给它使用,归还时放回堆顶。
  
  当页面用完时分配新页面在页面链表的未尾。
  
  需要客户程序额外记录一个页面索引值,归还时对号入坐。
  
  跟踪空闲对象数量,归还时判断空闲对象数量是否大于等于预定值(这里取2个页面数量值),
超过的话释放空闲页面,直至空闲对象数量小于等于预定值(这里取1个页面数量值)。
  
  每页面对象数量可通过带参数的构造函数设置,低于16时取16(如果低于16还不如用数组),
但具体取多少应根据实际情况而定,如果对象较小(低于128字节),此数值可以取大一点,如取
1024的话,一个页面也只占用128K的内存,对于现在的PC机来说微不足道。还有对象需要的数量变
动较大较频繁的话此值也应取大一点,过小的话分配和释放页面过多会降低程序运行速度。我推荐
的取值是估算你需要的最大量(这时对象请求归还操作在一个页面里,最佳情况),再计算目标平台内
存容量的1%(毕竟这不是程序的全部,还有其它模块也需要占用内存),权衡利弊取小值。


用法很简单:

        ObjectBuffer<int> ob;        //定义整型ObjectBuffer对象,无参构造,每页面对象数量取16
        int* p[48];                //客户程序装对象的数组
        unsigned long page[48];        //客户程序记录页面索引的数组
        for( int i = 0; i < 48; i++ )
        {
                p = NULL;
                page = 0;
                ob.RequestObject( &p, page );        //请求对象
                *p = 0;                        //请求来的对象是对象指针
        }
        for( i = 0; i < 32; i++ )
        {
                ob.ReturnObject( &p, page );        //归还对象
        }


作者心声:


    有用得着的话就拿去,但有一点就是请大家不要只看不说,大家多多提意见,比如发现什么错误啊,或者是
什么地方需要改进啊,或者是有更好的思路啊,大家一起分享哈嘛。我把它公布出来也是让大家一起分享嘛,所以请大家不
要只看不说,更或是用了也不说话。好了,不多说了,最后欢迎大家灌水,拍砖吧![em13][em13][em13][em13]

/*************ObjectBuffer1.0****************/
//对象缓冲器类模版,缓冲器预先分配一定数量的对象,当用到时就从缓冲器
//请求,不用时归还缓冲器,采用页链表分配技术使缓冲器理论上无分配上限
//
        const unsigned long ObjectOfPageMin = 16;                //每页中对象数量的最低值16
                                                                                                        //低于此值时缓冲器将失去意义
        template <class T>        
        class ObjectBuffer
        {
        public:
                ObjectBuffer();
                //ulObjectPage,每页上对象的数量,此值应根据对象大小、使用
                //情况统筹选取,以降低内存浪费。当小于16时取值16。
                ObjectBuffer( unsigned long ulObjectOfPage );
                ~ObjectBuffer();

                //当要用一个对象时,就用RequestObject请求
                bool RequestObject( T** pObjectPointer, unsigned long& ulPage );
                //当不用对象时调用ReturnObject归还
                bool ReturnObject( T** pObjectPointer, unsigned long& ulPage );
                //pObjectPointer参数为指向对象指针的指针 ulPage参数为对象所在的页
                //注意:当归还对象后,*pObjectPointer == NULL、ulPage == 0
               
        private:
                struct SPage
                {
                        T*                                m_pObjects;//对象数组
                        T**                                m_ppObjectStack;//对象堆,堆中存储的是对象指针
                        unsigned long        m_ulTop;                        //堆顶,当为0时说明对象已用完
                        unsigned long        m_ulObjectCount;        //对象数量
                        SPage*                        m_pFront;                        //前一页
                        SPage*                        m_pBack;                        //后一页
                       
                        SPage()
                        {
                                m_pObjects                = NULL;        //对象数组
                                m_ppObjectStack = NULL;        //对象堆,堆中存储的是对象指针
                                m_ulTop                        = 0;        //堆顶,当为0时说明对象已用完
                                m_pFront                = NULL;        //前一页
                                m_pBack                        = NULL;        //后一页
                                m_ulObjectCount = 0;        //对象数量
                                unsigned long ulObjectOfPage = ObjectOfPageMin;
                                m_pObjects = new T[ ulObjectOfPage ];
                                m_ppObjectStack = new T*[ ulObjectOfPage ];
                                if( NULL == m_pObjects || NULL == m_ppObjectStack )return;
                                for( int i = 0; i < ulObjectOfPage; i++ )
                             m_ppObjectStack = &m_pObjects;
                                m_ulTop = ulObjectOfPage;
                                m_ulObjectCount = ulObjectOfPage;        //对象数量
                        }
                        SPage( unsigned long ulObjectOfPage )
                        {
                                m_pObjects                = NULL;        //对象数组
                                m_ppObjectStack = NULL;        //对象堆,堆中存储的是对象指针
                                m_ulTop                        = 0;        //堆顶,当为0时说明对象已用完
                                m_pFront                = NULL;        //前一页
                                m_pBack                        = NULL;        //后一页
                                m_ulObjectCount = 0;        //对象数量
                                if( ulObjectOfPage < ObjectOfPageMin )ulObjectOfPage = ObjectOfPageMin;
                                m_pObjects = new T[ ulObjectOfPage ];
                                m_ppObjectStack = new T*[ ulObjectOfPage ];
                                if( NULL == m_pObjects || NULL == m_ppObjectStack )return;
                                for( int i = 0; i < ulObjectOfPage; i++ )
                               m_ppObjectStack = &m_pObjects;
                                m_ulTop = ulObjectOfPage;
                                m_ulObjectCount = ulObjectOfPage;        //对象数量
                        }
                        ~SPage(){ Release(); }
                        void Release()
                        {
                                if( NULL != m_pObjects )delete[] m_pObjects;
                                if( NULL != m_ppObjectStack )delete[] m_ppObjectStack;
                                m_pObjects                = NULL;        //对象数组
                                m_ppObjectStack = NULL;        //对象堆,堆中存储的是对象指针
                                m_ulObjectCount = 0;        //对象数量
                                m_ulTop                        = 0;        //堆顶,当为0时说明对象已用完
                                m_pFront                = NULL;        //前一页
                                m_pBack                        = NULL;        //后一页
                        }
                        bool IsEmpty()
                        {
                                return 0 == m_ulTop;
                        }
                        bool IsFull()
                        {
                                return m_ulTop == m_ulObjectCount;
                        }
                        void SetBack( SPage* pBack ){ m_pBack = pBack; }
                        void SetFront( SPage* pFront ){ m_pFront = pFront; }
                        T* RequestObject()
                        {
                                if( IsEmpty() )return NULL;
                                m_ulTop--;
                                return m_ppObjectStack[ m_ulTop ];
                        }
                        bool ReturnObject( T* pObject )
                        {
                                if( m_ulTop == m_ulObjectCount )return false;
                                //检查对象是否重复归还
                                for( unsigned long i = 0; i < m_ulTop; i++ )
                                {
                                        if( m_ppObjectStack[ i ] == pObject )return false;
                                }
                                m_ppObjectStack[ m_ulTop ] = pObject;
                                m_ulTop++;
                                return true;
                        }
                };

                SPage*                        m_pBeginPage;                        //页链表开始页
                SPage*                        m_pEndPage;                        //页链表结束页
                SPage*                        m_pCurrentPage;                        //当前操作页
                unsigned long        m_ulCurrentPageNumber;        //当前页编号
                unsigned long        m_ulPageCount;                //页数量
                unsigned long        m_ulObjectOfPage;                //每页中对象的数量
                unsigned long        m_ulIdleObjectCount;        //空闲对象数量
        };

        template <class T>
        ObjectBuffer<T>::ObjectBuffer()
        {
                m_pBeginPage        = NULL;                //页链表开始页
                m_pCurrentPage        = NULL;                //当前操作页
                m_pEndPage                = NULL;        //页链表结束页
                m_ulPageCount        = 0;                //页数量
                m_ulCurrentPageNumber = 0;        //当前页编号
                m_ulIdleObjectCount = 0;        //空闲对象数量
               
                m_ulObjectOfPage = ObjectOfPageMin;
                m_pCurrentPage = m_pEndPage = m_pBeginPage = new SPage( m_ulObjectOfPage );
                if( NULL == m_pBeginPage )return;
                m_ulPageCount = 1;
                m_ulCurrentPageNumber = 1;        //当前页编号
                m_ulIdleObjectCount += m_ulObjectOfPage;//空闲对象数量增加一个页面的数量
        }
        template <class T>
        ObjectBuffer<T>::ObjectBuffer( unsigned long ulObjectOfPage )
        {
                m_pBeginPage        = NULL;                //页链表开始页
                m_pCurrentPage        = NULL;                //当前操作页
                m_pEndPage                = NULL;        //页链表结束页
                m_ulPageCount        = 0;                //页数量
                m_ulCurrentPageNumber = 0;        //当前页编号
                m_ulIdleObjectCount = 0;        //空闲对象数量

                m_ulObjectOfPage = ulObjectOfPage;
                if( m_ulObjectOfPage < ObjectOfPageMin )m_ulObjectOfPage = ObjectOfPageMin;
                m_pCurrentPage = m_pEndPage = m_pBeginPage = new SPage( m_ulObjectOfPage );
                if( NULL == m_pBeginPage )return;
                m_ulPageCount = 1;
                m_ulCurrentPageNumber = 1;        //当前页编号
                m_ulIdleObjectCount += m_ulObjectOfPage;//空闲对象数量增加一个页面的数量
        }
        template <class T>
        ObjectBuffer<T>::~ObjectBuffer()
        {
                while( NULL != m_pBeginPage )
                {
                        m_pCurrentPage = m_pBeginPage;
                        m_pBeginPage = m_pBeginPage->m_pBack;
                        m_pCurrentPage->Release();
                        delete m_pCurrentPage;                       
                }

                m_pBeginPage        = NULL;                //页链表开始页
                m_pCurrentPage        = NULL;                //当前操作页
                m_pEndPage                = NULL;        //页链表结束页
                m_ulPageCount        = 0;                //页数量
                m_ulCurrentPageNumber = 0;        //当前页编号
                m_ulIdleObjectCount = 0;        //空闲对象数量
        }
       
        template <class T>
        bool ObjectBuffer<T>::RequestObject( T** pObjectPointer, unsigned long& ulPage )
        {
                for( unsigned long i = 0; i < m_ulPageCount; i++ )
                {
                        if( !m_pCurrentPage->IsEmpty() )//如果不为空就请求一个对象
                        {
                                *pObjectPointer = m_pCurrentPage->RequestObject();
                                ulPage = m_ulCurrentPageNumber;
                                m_ulIdleObjectCount--;        //一个对象成功分配,空闲对象数量减1
                                return true;                       
                        }
                        if( m_pCurrentPage == m_pEndPage )//如果到了未尾就从头开始
                        {
                                m_pCurrentPage = m_pBeginPage;
                                m_ulCurrentPageNumber = 1;
                        }
                        else
                        {
                                m_pCurrentPage = m_pCurrentPage->m_pBack;
                                m_ulCurrentPageNumber++;
                        }
                }

                //如果循环结束还没找到空闲对象,说明页面已经用完,需要分配新页面
                SPage* m_pNew = new SPage( m_ulObjectOfPage );
                if( NULL == m_pNew )return false;
                m_pNew->SetFront( m_pEndPage );
                m_pEndPage->SetBack( m_pNew );
                m_pEndPage = m_pNew;
                m_ulPageCount++;
                m_pCurrentPage = m_pEndPage;
                m_ulCurrentPageNumber = m_ulPageCount;
                m_ulIdleObjectCount += m_ulObjectOfPage;        //空闲对象数量增加一个页面的数量
                if( !m_pCurrentPage->IsEmpty() )//如果不为空就请求一个对象
                {
                        *pObjectPointer = m_pCurrentPage->RequestObject();
                        ulPage = m_ulCurrentPageNumber;
                        m_ulIdleObjectCount--;        //一个对象成功分配,空闲对象数量减1

                        return true;                       
                }
                return false;
        }
       
        template <class T>
        bool ObjectBuffer<T>::ReturnObject( T** pObjectPointer, unsigned long &ulPage )
        {
                if( NULL == pObjectPointer || NULL == *pObjectPointer ||
                                0 == ulPage || ulPage > m_ulPageCount )return false;
       
                if( ulPage > m_ulCurrentPageNumber )
                {
                        for( ; m_ulCurrentPageNumber < ulPage; m_ulCurrentPageNumber++ )
                        {       
                                m_pCurrentPage = m_pCurrentPage->m_pBack;
                        }
                }
                if( ulPage < m_ulCurrentPageNumber )
                {
                        for( ; m_ulCurrentPageNumber > ulPage; m_ulCurrentPageNumber-- )
                        {       
                                m_pCurrentPage = m_pCurrentPage->m_pFront;
                        }
                }
                if( !m_pCurrentPage->ReturnObject( *pObjectPointer ) )return false;
                *pObjectPointer = NULL;
                ulPage = 0;
                m_ulIdleObjectCount++;        //一个对象成功归还,空闲对象数量加1

                //如果空闲对象数量大于2倍页面数量,说明空闲对象太多了,需要释放一些以减少内存占用
                if( m_ulIdleObjectCount >= ( m_ulObjectOfPage * 2 ) )
                {
                        SPage* pTemp1 = m_pBeginPage;
                        SPage* pTemp2 = NULL;
                        //遍历页面链表,找出空闲页面并释放
                        while( NULL != pTemp1 )
                        {
                                if( m_ulIdleObjectCount <= m_ulObjectOfPage )break;

                                pTemp2 = pTemp1;
                                pTemp1 = pTemp1->m_pBack;//向后遍历

                                //如果为空闲页面
                                if( pTemp2->IsFull() )
                                {
                                        //如果是开始页面让开始页面指向下一页面
                                        if( pTemp2 == m_pBeginPage )
                                        {
                                                m_pBeginPage = pTemp2->m_pBack;//让下一页作为新的开始页
                                                m_pBeginPage->m_pFront = NULL;//让新开始页的前一页指向空
                                               
                                                //如果和当前页面相同让当前页面指向下一页面
                                                if( pTemp2 == m_pCurrentPage )
                                                {
                                                        m_pCurrentPage = pTemp2->m_pBack;
                                                }
                                                pTemp2->Release();
                                                delete pTemp2;
                                                pTemp2 = NULL;
                                                m_ulPageCount--;
                                                m_ulIdleObjectCount -= m_ulObjectOfPage;
                                                continue;
                                        }
                                        //如果是结束页面让结束页面指向上一页面
                                        if( pTemp2 == m_pEndPage )
                                        {
                                                m_pEndPage = pTemp2->m_pFront;//让上一页作为新的结束页
                                                m_pEndPage->m_pBack = NULL;//让新结束页的后一页指向空
                                               
                                                //如果和当前页面相同让当前页面指向上一页面
                                                if( pTemp2 == m_pCurrentPage )
                                                {
                                                        m_pCurrentPage = pTemp2->m_pFront;
                                                        m_ulCurrentPageNumber--;//当前页面编号减1
                                                }
                                                pTemp2->Release();
                                                delete pTemp2;
                                                pTemp2 = NULL;
                                                m_ulPageCount--;
                                                m_ulIdleObjectCount -= m_ulObjectOfPage;
                                                continue;
                                        }
                                        //既不是开始页也不是结束页,只是和当前页相同让当前页指向下一页
                                        if( pTemp2 == m_pCurrentPage )
                                        {
                                                m_pCurrentPage = pTemp2->m_pBack;
                                                m_ulCurrentPageNumber++;//当前页面编号增1
                                        }
                                        pTemp2->m_pFront->m_pBack = pTemp2->m_pBack;
                                        pTemp2->m_pBack->m_pFront = pTemp2->m_pFront;
                                        pTemp2->Release();
                                        delete pTemp2;
                                        pTemp2 = NULL;
                                        m_ulPageCount--;
                                        m_ulIdleObjectCount -= m_ulObjectOfPage;
                                }
                        }
                }
                return true;
        }
        //end

1

主题

15

帖子

15

积分

新手上路

Rank: 1

积分
15
发表于 2009-3-11 14:51:00 | 显示全部楼层

Re:小弟精心打造的一个对象缓冲器,可支持任何类型的对

这玩意没看能出有啥用。 [em12]

45

主题

157

帖子

169

积分

注册会员

Rank: 2

积分
169
QQ
 楼主| 发表于 2009-3-15 23:24:00 | 显示全部楼层

Re: Re:小弟精心打造的一个对象缓冲器,可支持任何类型

contra: Re:小弟精心打造的一个对象缓冲器,可支持任何类型的对象,有用就拿去

这玩意没看能出有啥用。 [em12]



  用在动态场景中,比如有这么一个场景,场景中有各种各样的对象,但每种对象的数量不确定,有时多一点,有时少一点,并且变化很频繁,就像网络游戏里某个地图上的玩家角色。这个东西就为这种需求而生,通过预先分配一定数量的对象作为缓冲器,当需要向场景中增加对象时,从对象缓冲器申请,当从场景中移走对象时,把其归回到对象缓冲器中,这样效率就大大提高,还不用时时担心内存泄漏,因为对象缓冲器会集中释放它所分配的对象。因为对象是一扎一扎的分配,比起要一个分配一个来说,还能降低内存碎片。

45

主题

157

帖子

169

积分

注册会员

Rank: 2

积分
169
QQ
 楼主| 发表于 2009-3-16 10:44:00 | 显示全部楼层

Re: 小弟精心打造的一个对象缓冲器,可支持任何类型的对

bluebaby9811: 小弟精心打造的一个对象缓冲器,可支持任何类型的对象,有用就拿去


设计思路:

  以页面为单位预先分配一定数量的对象给客户程序使用,用完再归...



  另一个版本,无需客户程序额外记录对象所在页号,降低了使用的复杂度,同时降低出错率。
  用法类似前一个版本:
  定义缓冲器时 ObjectBuffer<int> IntBuffer; 或 ObjectBuffer<int> IntBuffer(100);
  申请对象时 int* p = IntBuffer.RequestObject();
  归还对象时 IntBuffer.ReturnObject( &p );


[em13] 希望大家帮忙多测试测试,以期改进的更好用。[em13]


        /*************ObjectBuffer1.0****************/
        //对象缓冲器类模版,缓冲器预先分配一定数量的对象,当用到时就从缓冲器
        //请求,不用时归还缓冲器,采用页链表分配技术使缓冲器理论上无分配上限
        //
        template <class T>        
        class ObjectBuffer
        {
        public:
                ObjectBuffer();
                //ulObjectPage,每页上对象的数量,此值应根据对象大小、使用
                //情况统筹选取,以降低内存浪费。当小于16时取值16。
                ObjectBuffer( unsigned long ulObjectOfPage );
                ~ObjectBuffer();

                //当要用一个对象时,就用RequestObject请求
                T* RequestObject();
                //当不用对象时调用ReturnObject归还
                bool ReturnObject( T** ppObject );
                //注意:当归还对象后pObjectPointer指向NULL。
               
                enum
                {
                        ObjectOfPageMin = 16,                //每页中对象数量的最低值16
                                                                                //低于此值时缓冲器将失去意义
                };
        private:
                struct SPage
                {
                        T*                                m_pObjects;                        //对象数组
                        T*                                m_pEndObject;                //未尾对象地址       
                        T**                                m_ppObjectStack;        //对象堆,堆中存储的是对象指针
                        unsigned long        m_ulTop;                        //堆顶,当为0时说明对象已用完
                        unsigned long        m_ulObjectCount;        //对象数量
                        SPage*                        m_pFrontPage;                //前一页指针
                        SPage*                        m_pBackPage;                //后一页指针
                       
                        SPage()
                        {
                                m_pObjects                = NULL;        //对象数组
                                m_pEndObject        = NULL;        //未尾对象地址
                                m_ppObjectStack = NULL;        //对象堆,堆中存储的是对象指针
                                m_ulTop                        = 0;        //堆顶,当为0时说明对象已用完
                                m_ulObjectCount = 0;        //对象数量
                                m_pFrontPage        = NULL;        //前一页指针
                                m_pBackPage                = NULL;        //后一页指针
                               
                                unsigned long ulObjectOfPage = ObjectOfPageMin;
                                m_pObjects = new T[ ulObjectOfPage ];
                                m_pEndObject = &m_pObjects[ ulObjectOfPage - 1 ];
                                m_ppObjectStack = new T*[ ulObjectOfPage ];
                                if( NULL == m_pObjects || NULL == m_ppObjectStack )return;
                                for( int i = 0; i < ulObjectOfPage; i++ )m_ppObjectStack[ulObjectOfPage - i - 1] = &m_pObjects;
                                m_ulTop = ulObjectOfPage;
                                m_ulObjectCount = ulObjectOfPage;        //对象数量
                        }
       
       
                        SPage( unsigned long ulObjectOfPage )
                        {
                                m_pObjects                = NULL;        //对象数组
                                m_pEndObject        = NULL;        //未尾对象地址
                                m_ppObjectStack = NULL;        //对象堆,堆中存储的是对象指针
                                m_ulTop                        = 0;        //堆顶,当为0时说明对象已用完
                                m_ulObjectCount = 0;        //对象数量
                                m_pFrontPage        = NULL;        //前一页指针
                                m_pBackPage                = NULL;        //后一页指针

                                if( ulObjectOfPage < ObjectOfPageMin )ulObjectOfPage = ObjectOfPageMin;
                                m_pObjects = new T[ ulObjectOfPage ];
                                m_pEndObject = &m_pObjects[ ulObjectOfPage - 1 ];
                                m_ppObjectStack = new T*[ ulObjectOfPage ];
                                if( NULL == m_pObjects || NULL == m_ppObjectStack )return;
                                for( int i = 0; i < ulObjectOfPage; i++ )m_ppObjectStack[ulObjectOfPage - i - 1] = &m_pObjects;
                                m_ulTop = ulObjectOfPage;
                                m_ulObjectCount = ulObjectOfPage;        //对象数量
                        }

                        ~SPage(){ Release(); }
       
                        void Release()
                        {
                                if( NULL != m_pObjects )delete[] m_pObjects;
                                if( NULL != m_ppObjectStack )delete[] m_ppObjectStack;
                                m_pObjects                = NULL;        //对象数组
                                m_pEndObject        = NULL;        //未尾对象地址
                                m_ppObjectStack = NULL;        //对象堆,堆中存储的是对象指针
                                m_ulObjectCount = 0;        //对象数量
                                m_ulTop                        = 0;        //堆顶,当为0时说明对象已用完
                                m_pFrontPage                = NULL;        //前一页
                                m_pBackPage                        = NULL;        //后一页
                        }
               
                        bool IsEmpty(){        return 0 == m_ulTop; }
                        bool IsFull(){ return m_ulTop == m_ulObjectCount; }
               
                        void SetBack( SPage* pBack ){ m_pBackPage = pBack; }
                        void SetFront( SPage* pFront ){ m_pFrontPage = pFront; }

                        bool IsMember( T* pObject ){ return ( pObject >= m_pObjects ) && ( pObject <= m_pEndObject ); }
               
                        T* RequestObject()
                        {
                                m_ulTop--;
                                return m_ppObjectStack[ m_ulTop ];
                        }

                        bool ReturnObject( T* pObject )
                        {
                                if( m_ulTop == m_ulObjectCount )return false;
                                //检查对象是否重复归还
                                for( unsigned long i = 0; i < m_ulTop; i++ )
                                {
                                        if( m_ppObjectStack[ i ] == pObject )return false;
                                }
                                m_ppObjectStack[ m_ulTop ] = pObject;
                                m_ulTop++;
                                return true;
                        }
                };

                SPage*                        m_pBeginPage;                        //页链表开始页
                SPage*                        m_pEndPage;                                //页链表结束页
                SPage*                        m_pCurrentPage;                        //当前操作页
                unsigned long        m_ulCurrentPageNumber;        //当前页编号
                unsigned long        m_ulPageCount;                        //页数量
                unsigned long        m_ulObjectOfPage;                //每页中对象的数量
                unsigned long        m_ulIdleObjectCount;        //空闲对象数量
        };
        //end

        //////////////////////////////////
        //ObjectBuffer Class template implement
        //////////////////////////////////////
        template <class T>
        ObjectBuffer<T>::ObjectBuffer()
        {
                m_pBeginPage        = NULL;                //页链表开始页
                m_pCurrentPage        = NULL;                //当前操作页
                m_pEndPage                = NULL;                //页链表结束页
                m_ulPageCount        = 0;                //页数量
                m_ulCurrentPageNumber = 0;        //当前页编号
                m_ulIdleObjectCount = 0;        //空闲对象数量
               
                m_ulObjectOfPage = ObjectOfPageMin;
                m_pCurrentPage = m_pEndPage = m_pBeginPage = new SPage( m_ulObjectOfPage );
                if( NULL == m_pBeginPage )return;
                m_ulPageCount = 1;
                m_ulCurrentPageNumber = 1;        //当前页编号
                m_ulIdleObjectCount += m_ulObjectOfPage;//空闲对象数量增加一个页面的数量
        }
        template <class T>
        ObjectBuffer<T>::ObjectBuffer( unsigned long ulObjectOfPage )
        {
                m_pBeginPage        = NULL;                //页链表开始页
                m_pCurrentPage        = NULL;                //当前操作页
                m_pEndPage                = NULL;                //页链表结束页
                m_ulPageCount        = 0;                //页数量
                m_ulCurrentPageNumber = 0;        //当前页编号
                m_ulIdleObjectCount = 0;        //空闲对象数量

                m_ulObjectOfPage = ulObjectOfPage;
                if( m_ulObjectOfPage < ObjectOfPageMin )m_ulObjectOfPage = ObjectOfPageMin;
                m_pCurrentPage = m_pEndPage = m_pBeginPage = new SPage( m_ulObjectOfPage );
                if( NULL == m_pBeginPage )return;
                m_ulPageCount = 1;
                m_ulCurrentPageNumber = 1;        //当前页编号
                m_ulIdleObjectCount += m_ulObjectOfPage;//空闲对象数量增加一个页面的数量
        }
        template <class T>
        ObjectBuffer<T>::~ObjectBuffer()
        {
                while( NULL != m_pBeginPage )
                {
                        m_pCurrentPage = m_pBeginPage;
                        m_pBeginPage = m_pBeginPage->m_pBackPage;
                        m_pCurrentPage->Release();
                        delete m_pCurrentPage;                       
                }

                m_pBeginPage        = NULL;                //页链表开始页
                m_pCurrentPage        = NULL;                //当前操作页
                m_pEndPage                = NULL;                //页链表结束页
                m_ulPageCount        = 0;                //页数量
                m_ulCurrentPageNumber = 0;        //当前页编号
                m_ulIdleObjectCount = 0;        //空闲对象数量
        }
       
        template <class T>
        T* ObjectBuffer<T>::RequestObject()
        {
                for( unsigned long i = 0; i < m_ulPageCount; i++ )
                {
                        if( !m_pCurrentPage->IsEmpty() )//如果不为空就请求一个对象
                        {
                                m_ulIdleObjectCount--;        //一个对象成功分配,空闲对象数量减1
                                return m_pCurrentPage->RequestObject();                       
                        }
                        if( m_pCurrentPage == m_pEndPage )//如果到了未尾就从头开始
                        {
                                m_pCurrentPage = m_pBeginPage;
                                m_ulCurrentPageNumber = 1;
                        }
                        else
                        {
                                m_pCurrentPage = m_pCurrentPage->m_pBackPage;
                                m_ulCurrentPageNumber++;
                        }
                }

                //如果循环结束还没找到空闲对象,说明页面已经用完,需要分配新页面
                SPage* m_pNew = new SPage( m_ulObjectOfPage );
                if( NULL == m_pNew )return NULL;
                m_pNew->SetFront( m_pEndPage );
                m_pEndPage->SetBack( m_pNew );
                m_pEndPage = m_pNew;
                m_ulPageCount++;
                m_pCurrentPage = m_pEndPage;
                m_ulCurrentPageNumber = m_ulPageCount;
                m_ulIdleObjectCount += m_ulObjectOfPage;        //空闲对象数量增加一个页面的数量
                m_ulIdleObjectCount--;        //一个对象成功分配,空闲对象数量减1
                return m_pCurrentPage->RequestObject();
        }
       
        template <class T>
        bool ObjectBuffer<T>::ReturnObject( T** ppObject )
        {
                if( NULL == ppObject || NULL == *ppObject )return false;
       
                for( unsigned long i = 0; i < m_ulPageCount; i++ )
                {
                        if( m_pCurrentPage->IsMember( *ppObject ) )//对象是否属于此页
                        {
                                if( !m_pCurrentPage->ReturnObject( *ppObject ) )return false;
                                *ppObject = NULL;
                                m_ulIdleObjectCount++;        //一个对象成功归还,空闲对象数量加1
                                continue;
                        }
                        if( m_pCurrentPage == m_pEndPage )//如果到了未尾就从头开始
                        {
                                m_pCurrentPage = m_pBeginPage;
                                m_ulCurrentPageNumber = 1;
                        }
                        else
                        {
                                m_pCurrentPage = m_pCurrentPage->m_pBackPage;
                                m_ulCurrentPageNumber++;
                        }
                }
       
                //如果空闲对象数量大于2倍页面数量,说明空闲对象太多了,需要释放一些以减少内存占用
                if( m_ulIdleObjectCount >= ( m_ulObjectOfPage + m_ulObjectOfPage ) )
                {
                        SPage* pTemp1 = m_pBeginPage;
                        SPage* pTemp2 = NULL;
                        //遍历页面链表,找出空闲页面并释放
                        while( NULL != pTemp1 )
                        {
                                if( m_ulIdleObjectCount <= m_ulObjectOfPage )break;

                                pTemp2 = pTemp1;
                                pTemp1 = pTemp1->m_pBackPage;//向后遍历

                                //如果为空闲页面
                                if( pTemp2->IsFull() )
                                {
                                        //如果是开始页面让开始页面指向下一页面
                                        if( pTemp2 == m_pBeginPage )
                                        {
                                                m_pBeginPage = pTemp2->m_pBackPage;//让下一页面作为新的开始页面
                                                m_pBeginPage->m_pFrontPage = NULL;//让新开始页面的前一页面指向空
                                               
                                                //如果和当前页面相同让当前页面指向下一页面
                                                if( pTemp2 == m_pCurrentPage )
                                                {
                                                        m_pCurrentPage = pTemp2->m_pBackPage;
                                                }
                                                pTemp2->Release();
                                                delete pTemp2;
                                                pTemp2 = NULL;
                                                m_ulPageCount--;
                                                m_ulIdleObjectCount -= m_ulObjectOfPage;
                                                continue;
                                        }
                                        //如果是结束页面让结束页面指向上一页面
                                        if( pTemp2 == m_pEndPage )
                                        {
                                                m_pEndPage = pTemp2->m_pFrontPage;//让上一页面作为新的结束页面
                                                m_pEndPage->m_pBackPage = NULL;//让新结束页面的后一页面指向空
                                               
                                                //如果和当前页面相同让当前页面指向上一页面
                                                if( pTemp2 == m_pCurrentPage )
                                                {
                                                        m_pCurrentPage = pTemp2->m_pFrontPage;
                                                        m_ulCurrentPageNumber--;//当前页面编号减1
                                                }
                                                pTemp2->Release();
                                                delete pTemp2;
                                                pTemp2 = NULL;
                                                m_ulPageCount--;
                                                m_ulIdleObjectCount -= m_ulObjectOfPage;
                                                continue;
                                        }
                                        //既不是开始页面也不是结束页面,只是和当前页面相同让当前页面指向下一页面
                                        if( pTemp2 == m_pCurrentPage )
                                        {
                                                m_pCurrentPage = pTemp2->m_pBackPage;
                                                m_ulCurrentPageNumber++;//当前页面编号增1
                                        }
                                        pTemp2->m_pFrontPage->m_pBackPage = pTemp2->m_pBackPage;
                                        pTemp2->m_pBackPage->m_pFrontPage = pTemp2->m_pFrontPage;
                                        pTemp2->Release();
                                        delete pTemp2;
                                        pTemp2 = NULL;
                                        m_ulPageCount--;
                                        m_ulIdleObjectCount -= m_ulObjectOfPage;
                                }
                        }
                }
                return true;
        }
       
        ///////////////////////////////
        //end
        ////////////////////////////////////

3

主题

263

帖子

267

积分

中级会员

Rank: 3Rank: 3

积分
267
发表于 2009-3-27 19:15:00 | 显示全部楼层

Re:小弟精心打造的一个对象缓冲器,可支持任何类型的对

好像在哪儿见过...
貌似是在Gameres的其他坛子里..

0

主题

1

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2009-3-29 20:40:00 | 显示全部楼层

Re: 小弟精心打造的一个对象缓冲器,可支持任何类型的对

请问下,页中的对象数量为什么要至少16个? 小对象的话,这么理解对吗,比如int类型的 , 16个或大于16个一次分配,可以减少开销,并避免内存碎片。  
但是比如存的类型很大,比如一个类型大小为12k的对象, 页中1个对象和至少16个对象有区别没?

4

主题

95

帖子

99

积分

注册会员

Rank: 2

积分
99
发表于 2009-4-8 15:16:00 | 显示全部楼层

Re: 小弟精心打造的一个对象缓冲器,可支持任何类型的对

直接用boost的pool库不就可以了?

boost::pool<> p(sizeof(int));
                      ^^^^^^^^^^^
                      指定每次分配的块的大小
      for (int i = 0; i < 10000; ++i)
      {
        int * const t = p.malloc();
                        pool分配指定大小的内存块;需要的时候,pool会向系统
                        申请大块内存。
        ... // Do something with t; don't take the time to free() it
        p.free( t );
        // 释放内存块,交还给pool,不是返回给系统。

常用的类库还是直接用标准的好

51

主题

3551

帖子

3655

积分

论坛元老

Rank: 8Rank: 8

积分
3655
发表于 2009-4-9 17:58:00 | 显示全部楼层

Re:小弟精心打造的一个对象缓冲器,可支持任何类型的对

当需要向场景中增加对象时,从对象缓冲器申请《----貌似这个是类似cpu的二级缓存机制

45

主题

157

帖子

169

积分

注册会员

Rank: 2

积分
169
QQ
 楼主| 发表于 2009-4-14 19:17:00 | 显示全部楼层

Re: Re: 小弟精心打造的一个对象缓冲器,可支持任何类型

fananchong: Re: 小弟精心打造的一个对象缓冲器,可支持任何类型的对象,有用就拿去

请问下,页中的对象数量为什么要至少16个? 小对象的话,这么理解对吗,比如int类型的 , 16个或大于16个一...


  在我看来,低于16个的话,说明你的用量不大,用此缓冲器还不如new来得直接高效。

45

主题

157

帖子

169

积分

注册会员

Rank: 2

积分
169
QQ
 楼主| 发表于 2009-4-14 19:25:00 | 显示全部楼层

Re: Re: 小弟精心打造的一个对象缓冲器,可支持任何类型

huangyous: Re: 小弟精心打造的一个对象缓冲器,可支持任何类型的对象,有用就拿去

直接用boost的pool库不就可以了?

boost::pool<> p(sizeof(int));
                      ^^^^^^...


  有现成的用固然是好,但我觉得自己搞一个也可以学到很多东西。不过小弟还没研究过boost库,过哈向huangyous前辈学习学习,呵呵。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-12-20 14:17

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表