#ifndef T_CACHE #define T_CACHE #include "../Utility.h" #include #include using namespace std; ////////////////////////////////////////////////////////////////////////// //使用以下内存模板管理小对象, from Andrew Kirmse, added by dzj, 06.03.17; ////////////////////////////////////////////////////////////////////////// /** Copyright (C) Andrew Kirmse, 2001. * All rights reserved worldwide. * * This software is provided "as is" without express or implied * warranties. You may freely copy and compile this source into * applications you distribute provided that the copyright text * below is included in the resulting source code, for example: * "Portions Copyright (C) Andrew Kirmse, 2001" */ #ifndef _CACHE_H #define _CACHE_H /*********************************************************************** ** ** ** TCache ** ** ** ** Objects can be released to the cache in arbitrary order. ** ** ** ***********************************************************************/ /** ///!!!注意:任何类,一旦其某些实例经过了TCache管理,则所有该类对象都必须从TCache管理的池中分配, ///不可自行new,不可定义局部变量,不可定义静态变量,不可memset; ///因为使用了下述的池管理策略,且所有的对象最后都要通过对象池回收,不遵守上述约定会造成内存错误; */ #define PoolFlagDefine \ private:\ unsigned long dwUID;\ bool bIsPoolObj; \ public:\ bool IsStillValid( unsigned long orgUID ) { return (dwUID == orgUID); };\ unsigned long GetUID() { return dwUID; };\ void InitUID() { dwUID = 0ul; };\ void IncUID() { ++ dwUID; };\ void SetPoolFlag() { bIsPoolObj = true; }; \ void ClearPoolFlag() { bIsPoolObj = false; }; \ bool IsPoolObj() { return bIsPoolObj; }; \ void PoolObjInit template class TCache { private: TCache();//屏蔽此操作; public: explicit TCache(unsigned int MaxCacheSize) : mMaxCacheSize(MaxCacheSize) { //构造时预先生成好池中的内存结构, by dzj, 07.12.03; m_pArray = NEW T[MaxCacheSize]; if ( NULL != m_pArray ) { for ( unsigned int i=0; iIncUID();取的时候不需要增ID号,因为回收的时候已经增了; pItem->PoolObjInit(); } return pItem; } // Creates a new object on the help if no objects // available in cache T* RetrieveOrCreate() { T* pItem = NULL; if ( !(mCache.empty()) )//保护时间尽量短点,只有非空时才进保护区去试图取一个; { #ifdef ACE_WIN32 DsMutex guard(mLock); #else //ACE_WIN32 ACE_GUARD_RETURN( ACE_Thread_Mutex, guard, mLock, NULL ); #endif //ACE_WIN32 if ( !(mCache.empty()) ) //如果此时空,说明进保护区之前mCache又被取空 { pItem = mCache.front(); mCache.pop_front(); } } if ( NULL == pItem ) //mCache已被取空, NEW一个非池中对象; { pItem = NEW T; if ( NULL != pItem ) { pItem->ClearPoolFlag();//不是初始池中对象; } } if ( NULL != pItem ) { //Item->IncUID();取的时候不需要增ID号,因为回收的时候已经增了; pItem->PoolObjInit(); } return pItem; } void Release(T* pItem) { if ( NULL == pItem ) { return; } if ( pItem->IsPoolObj() ) { pItem->IncUID();//递增ID号,以防止指针悬挂; pItem->PoolObjInit(); if ( true ) //尽量短地保护mCache; { #ifdef ACE_WIN32 DsMutex guard(mLock); #else //ACE_WIN32 ACE_GUARD( ACE_Thread_Mutex, guard, mLock ); #endif //ACE_WIN32 mCache.push_back( pItem ); } } else { delete pItem; pItem = NULL; } } void Clear() { #ifdef ACE_WIN32 DsMutex guard(mLock); #else //ACE_WIN32 ACE_GUARD( ACE_Thread_Mutex, guard, mLock ); #endif //ACE_WIN32 if(m_pArray != NULL) { delete[] m_pArray;m_pArray=NULL; } mCache.clear(); } unsigned int GetMaxCacheSize() const { return mMaxCacheSize; } unsigned int GetCurrentCacheSize() const { return mCache.size(); } private: // Private data unsigned int mMaxCacheSize; //std::vector mCache; //改为list,以便给回收到重用之间留开一定的空闲时间,减少过快被重用,导致重用后的物体被错误地认为是重用前的物体这种错误,虽然不能完全杜绝,但至少可以大大减小其发生的概率; std::list mCache; T* m_pArray; #ifdef ACE_WIN32 DsCS mLock; #else //ACE_WIN32 ACE_Thread_Mutex mLock; #endif //ACE_WIN32 }; #endif // #define _CACHE_H ////////////////////////////////////////////////////////////////////////// //使用以上内存模板管理小对象; ////////////////////////////////////////////////////////////////////////// ///保存唯一池对象实例(每次池回收后都不同,用于防止悬挂指针或在实例重用后的不正确使用), /// 通过构造赋初值,通过GetUniqueObj()得到真正实例,一旦实例已被回收,GetUniqueObj()将返回空; ///其保存的池对象必须通过Retrieve而不是RetrieveOrCreate得到; template class UniqueObj { public: UniqueObj() : m_realUID(0),m_pObj(NULL) { }; ~UniqueObj() { m_pObj = NULL; m_realUID = 0; } PoolFlagDefine() { m_pObj = NULL; m_realUID = 0; } public: //初始化自身指向pObj with UID = pObj's current UID; void Init( T* pObj ) { m_pObj = pObj; m_realUID = 0; if ( NULL != m_pObj ) { m_realUID = pObj->GetUID(); } } public: //取自身保存的pObj,如果该pObj已被回收,则返回空; T* GetUniqueObj() { if ( NULL == m_pObj ) { return NULL; } else { //传入期望的ID号,看现在这个实例是否仍为原来那一个; //前提,CPlayer对象只会回收到对象池,而不会真正释放; if ( m_pObj->IsStillValid( m_realUID) ) { return m_pObj; } else { m_pObj = NULL;//原来的实例已无效,重置之; return NULL; } } } //得到本实例期望指向的pObj的UID; unsigned long GetExpectUID() { return m_realUID; } private: unsigned long m_realUID;//本实例期望指向的pObj的UID; T* m_pObj; }; #endif //T_CACHE