//////////////////////////////////////////////////////
// = LIBRARY
// = FILENAME  otstr.h
// = AUTHOR    Shen beide
// = MODIFY    2006-01
//////////////////////////////////////////////////////

#ifndef MY_MEMPOOL_H
#define MY_MEMPOOL_H

///////////////////////////////////////////////////////////
// CMemPool         static memory malloc and free
//
// CObjectPool <T>  T's static memory new and delete 
//
// CObjectPool_<T>  T's static memory new and delete 
//                  with improved strategy
//
// CObjectsPool     Objects's static memory new and delete 
//                  
///////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>

#include "PubHeader.h"
#include "Base.h"
#include "ObList.h"
#include "otstr.h"
#include "Tracer.h"

class CMemBlockList
{
public:
    ObList      m_IdleMemList;
    int         m_nMemSize;

    long        m_nActiveMemNum;

    int         m_IdleTimeTicket;

public:
    CMemBlockList();
   ~CMemBlockList();
};


#ifdef _DLL_PROJECT
class CLASS_EXPORT CMemPool
#else
class CMemPool
#endif
{
public:
    CMemPool();
   ~CMemPool();

    virtual bool  setparam(int nBitNumber,int nMaxTimesOfBaseMemBlock);
                           //  MemBlock = 1<<BitNumber   定义了内存块增量 1-20   ( 2 Byte - 1 M Byte )
                           //  nMaxTimesOfBaseMemBlock   该倍数定义保存不同内存块的队列个数 1-254
                           //                            最大可保存内存块大小 = MemBlock * nMaxTimesOfBaseMemBlock
                           //  Sample: BitNumber=5, nMaxTimesOfBaseMemBlock=8
                           //          Queue = 32*1, 32*2, 32*3, ... 32*8 ( 超过大小的不作队列处理 )

    virtual char* malloc_ (long  size, bool bMemZero=false);  
    virtual void  free_   (char* pbuffer);
    virtual char* realloc_(char *pOldbuffer, long newsize);

    void  GetInfo(OTSTR& str);

protected:
    CMemBlockList* m_pBlockList;
    int            m_nActiveOverflowMemNum;

    int            m_nBitNumber;
    int            m_nMaxListIndex;
};


///////////////////////////////////////////////////////////////
#ifdef _DLL_PROJECT
template<class OBJECTTYPE>class CLASS_EXPORT CObjectPool
#else
template<class OBJECTTYPE>class CObjectPool
#endif
{
private:
    ObList        m_IdleObjectList;
    long          m_nActiveMemNum;

    unsigned long poolsize;
    
public:    
    CObjectPool()
    {
        m_nActiveMemNum=0;
        poolsize       =0;
        m_IdleObjectList.Setpoolsize(32000);
    }

    ~CObjectPool()
    {
        if (m_nActiveMemNum!=0) 
        {
            TRACE1_("ObjectPool_ destruct found err, nActiveMemNum=%ld",m_nActiveMemNum);
        }
        OBJECTTYPE* pObject;
        while(!m_IdleObjectList.IsEmpty())
        {
            pObject=(OBJECTTYPE*)(m_IdleObjectList.RemoveHead());
            delete pObject;
        }
    }

    void  Setpoolsize(unsigned long default_poolsize=32000)
    // poolsize=0 时, 直接使用系统 new, delete 
    // poolsize>0 时, 采用优化静态内存分配, 可以提高分配效率
    {
        poolsize=default_poolsize;
    }

    inline OBJECTTYPE* new_()
    {
        OBJECTTYPE* pObject;
        if (poolsize==0)
        {
            pObject=new OBJECTTYPE();
        }
        else
        {
            pObject=(OBJECTTYPE*)(m_IdleObjectList.RemoveHead());
            if (pObject==NULL)
            {
                pObject=new OBJECTTYPE();
            }
        }

        if (pObject)
        {
            pObject->OnCreate();
        
            m_nActiveMemNum++;
        }

        return pObject;
    }

    inline void delete_(OBJECTTYPE* pObject,bool bCheck=false)
    {
        if (pObject==NULL) return;

        if (bCheck)
        {
            for(int i=0;i<m_IdleObjectList.GetCount();i++)
            {
                if ( ((OBJECTTYPE*)m_IdleObjectList.GetAt(i))==pObject )
                {
                    return;
                }
            }
        }
        
        pObject->OnDestroy();

        if (m_nActiveMemNum+m_IdleObjectList.GetCount()>(long)poolsize)
            delete pObject;
          else      
            m_IdleObjectList.AddTail(pObject);

        m_nActiveMemNum--;
    }

    void GetInfo(OTSTR& str)
    {
        str.Format("Active: %d   Idle: %d",m_nActiveMemNum,m_IdleObjectList.GetCount());
    }
};

///////////////////////////////////////////////////////////////
#ifdef _DLL_PROJECT
template<class OBJECTTYPE>class CLASS_EXPORT CObjectPool_
#else
template<class OBJECTTYPE>class CObjectPool_
#endif
{
private:
    ObList      m_IdleObjectList;
    long        m_nActiveMemNum;
    
    ObList      m_BlockBufferList;
    int         m_nObjectPerBlock;
    
public:    
    CObjectPool_()
    {
        m_nActiveMemNum  =0;
        m_nObjectPerBlock=10;
        m_IdleObjectList.Setpoolsize(32000);
    }
    
    ~CObjectPool_()
    {
        if (m_nActiveMemNum!=0) 
        {
            TRACE1_("ObjectPool_ destruct found err, nActiveMemNum=%ld",m_nActiveMemNum);
        }
        OBJECTTYPE* pObList;
        while(!m_BlockBufferList.IsEmpty())
        {
            pObList=(OBJECTTYPE*)m_BlockBufferList.RemoveHead();
            delete[] pObList ;
        }
        m_IdleObjectList.RemoveAll();
    }
    
    inline void setparam(int nInitialObjectNum, int nObjectPerBlock)
    {
        if (nInitialObjectNum>0)
        {
            AddNewIdleObjects(nInitialObjectNum);
        }
        m_nObjectPerBlock=nObjectPerBlock;
    }
    
    inline OBJECTTYPE* new_()
    {
        if (m_IdleObjectList.IsEmpty())
        {
            AddNewIdleObjects(m_nObjectPerBlock);
        }
        
        OBJECTTYPE* pObject;
        pObject=(OBJECTTYPE*)m_IdleObjectList.RemoveHead();
        if (pObject)
        {
            pObject->OnCreate();
        
            m_nActiveMemNum++;
        }    
        return pObject;
    }
    
    inline void delete_(OBJECTTYPE* pObject,bool bCheck=false)
    {
        if (pObject==NULL) return;
     
        if (bCheck)
        {
            for(int i=0;i<m_IdleObjectList.GetCount();i++)
            {
                if ( ((OBJECTTYPE*)m_IdleObjectList.GetAt(i))==pObject )
                {
                    return;
                }
            }
        }

        pObject->OnDestroy();
        
        m_IdleObjectList.AddTail(pObject);
        
        m_nActiveMemNum--;
    }
    
    virtual void AddNewIdleObjects(int num)
    {
        OBJECTTYPE* pObjList= new OBJECTTYPE [num];
        if (pObjList)
        {
            m_BlockBufferList.AddTail(pObjList);
            
            for(int i=0;i<num;i++) 
                m_IdleObjectList.AddTail(&pObjList[i]);
        }
    }
    
    void GetInfo(OTSTR& str)
    {
        str.Format("Active: %d   Idle: %d   Block: %d",m_nActiveMemNum,m_IdleObjectList.GetCount(),m_BlockBufferList.GetCount());
    }
};



//////////////////////////////////////////////////////////////
class TObjectsPool
{
protected:
    enum { MAX_OBJECTTYPEID=20 };
    
    class CObjectPoolItem
    {
    public:
        ObList      m_IdleObjectList;
        long        m_nActiveMemNum;
    };
    
public:
    TObjectsPool();	
   ~TObjectsPool();	
        
    /////////////////////////////////////////////////////
        
    TObject* new_(unsigned int ObjectTypeId);
    void  delete_(TObject* pObject);
    
    /////////////////////////////////////////////////////////////
    // FOR USER OVERWRITE
    virtual TObject* MallocObject(int ObjectTypeId)
    {
        TObject* pObject=NULL;
        
        if ( ObjectTypeId==TObject::ObjectId() ) 
        {
            pObject=new TObject();
        }
        return pObject;
    }
    
private:
    CObjectPoolItem  m_ObjectsPoolList[MAX_OBJECTTYPEID+1];
};


#endif /* _H */

































































