537 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			537 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | ||
|  Handle类通常是只读的无符号整数。虽然可以安全地将其设为空来重置句柄,但句柄一旦创建就不应该再修改。
 | ||
|  注意,Handle是参数化的类,需要一个TAG类型来完整定义。
 | ||
|  模板参数TAG除了区分句柄类型外不起任何作用,TAG类型的对象在系统任何地方都不会被用到。
 | ||
|  这么做的原因是为了保证类型安全。使用参数化的Handle类型可以确保,如果向期望获取某种类型句柄的
 | ||
|  函数传递另外一种类型的句柄,则不会被编译通过。
 | ||
|  因此为了保障类型安全,我们创建一个新的句柄类型,
 | ||
|  作为一个唯一符号并被用作Handle类型的参数。TAG类型可以是任何形式的类型.
 | ||
| */
 | ||
|  
 | ||
| #ifndef _DEBUG
 | ||
| #include <new>
 | ||
| //#include <time.h>
 | ||
| #endif
 | ||
| //#include <vector>
 | ||
| //#include <cassert>
 | ||
| //实现对象的重用,而且管理实体
 | ||
| //参见: http://hi.baidu.com/zyb_debug/blog/item/eaf6ea8ce55f291bb21bba4c.html 
 | ||
| 
 | ||
| #pragma once
 | ||
| 
 | ||
| enum
 | ||
| {
 | ||
| 	// sizes to use for bit fields 使用位域(bit fields)的大小
 | ||
| 	MAX_BITS_INDEX = 21,
 | ||
| 	MAX_BITS_MAGIC = 11,
 | ||
| 
 | ||
| 	// sizes to compare against for asserting dereferences
 | ||
| 	MAX_INDEX = ( 1 << MAX_BITS_INDEX) - 1,
 | ||
| 	MAX_MAGIC = ( 1 << MAX_BITS_MAGIC) - 1,
 | ||
| 
 | ||
| 	//INVALID_INDEX =( 1 << MAX_BITS_INDEX),   //非法的INDEX
 | ||
| };
 | ||
| 
 | ||
| //TAG在这里并没有什么用处,
 | ||
| template <typename TAG>
 | ||
| class Handle
 | ||
| {
 | ||
| 	union
 | ||
| 	{
 | ||
| 		struct
 | ||
| 		{
 | ||
| 			unsigned m_Index : MAX_BITS_INDEX; // index into resource array 资源数组的索引
 | ||
| 			unsigned m_Magic : MAX_BITS_MAGIC; // magic number to check     需要检查的魔术数
 | ||
| 		};
 | ||
| 		unsigned int m_Handle;
 | ||
| 	};
 | ||
| 
 | ||
| public:
 | ||
| 	
 | ||
| 	// Lifetime.生命期
 | ||
| 
 | ||
| 	Handle( void ) : m_Handle( 0 ) { }
 | ||
| 	Handle( unsigned nHandle )  {m_Handle= nHandle ;} //
 | ||
| 
 | ||
| 	void Init( unsigned int index )
 | ||
| 	{
 | ||
| 		
 | ||
| 		DbgAssert( IsNull() );             // don't allow reassignment 不允许重新赋值
 | ||
| 		DbgAssert( index <=MAX_INDEX );   // verify range 有限范围验证
 | ||
| 
 | ||
| 		//魔数初始化修改为一个随机数,避免出现一些特殊情况,增加服务器重启后可靠性
 | ||
| 		static unsigned int s_AutoMagic = rand();
 | ||
| 		IncMagicNumImpl(s_AutoMagic);
 | ||
| 
 | ||
| 		m_Index = index;
 | ||
| 		m_Magic = s_AutoMagic;
 | ||
| 	}
 | ||
| 
 | ||
| 	inline void updateMagic() {
 | ||
| 		unsigned int magic = m_Magic;
 | ||
| 		IncMagicNumImpl(magic);
 | ||
| 		m_Magic = magic;
 | ||
| 	}
 | ||
| 
 | ||
| 	// Query.查询
 | ||
| 
 | ||
| 	inline unsigned int GetIndex ( void ) const { return ( m_Index ); }
 | ||
| 	inline unsigned int GetMagic ( void ) const { return ( m_Magic ); }
 | ||
| 	inline unsigned int GetHandle( void ) const { return ( m_Handle ); }
 | ||
| 	
 | ||
| 	bool         IsNull   ( void ) const { return ( !m_Handle ); }
 | ||
| 	inline unsigned GetMaxIndex(){return MAX_INDEX;}
 | ||
| 	operator unsigned int ( void ) const { return ( m_Handle ); }
 | ||
| 
 | ||
| protected:
 | ||
| 	inline void IncMagicNumImpl(unsigned int &magic)
 | ||
| 	{
 | ||
| 		if ( ++magic > MAX_MAGIC )
 | ||
| 			magic = 1;    // 0 is used for "null handle"
 | ||
| 	}
 | ||
| };
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| template <typename DATA, typename HANDLE,int ONE_CHUNK_COUNT =1024>
 | ||
| class HandleMgr
 | ||
| {
 | ||
| public:
 | ||
| 	typedef DATA	DataType;
 | ||
| 	typedef HANDLE	HandleType;
 | ||
| 	//typedef HandleMgrStat Inherited;
 | ||
| 
 | ||
| 	 HandleMgr(LPCTSTR lpszDesc);
 | ||
| 
 | ||
| 	~HandleMgr( ) 
 | ||
| 	{
 | ||
| 		Empty();
 | ||
| 	}
 | ||
| 	
 | ||
| 	
 | ||
| 	//申请一个数据指针
 | ||
| 	DATA* Acquire( HANDLE& handle );
 | ||
| 	
 | ||
| 	//不使用指针,放到缓存池里去
 | ||
| 	void Release( HANDLE handle );
 | ||
| 
 | ||
| 	// 重新请求一个新句柄
 | ||
| 	bool ReNew( HANDLE &handle);	
 | ||
| 
 | ||
| 	// 通过handle返回数据的指针
 | ||
| 	DATA*       GetDataPtr( HANDLE handle );
 | ||
| 	const DATA* GetDataPtr( HANDLE handle ) const;
 | ||
| 
 | ||
| 	// other query 其他查询
 | ||
| 
 | ||
| 	inline unsigned int GetUsedHandleCount( void ) const
 | ||
| 	{ 
 | ||
| 		return ( m_nUsedCount ); 
 | ||
| 	}
 | ||
| 	inline UINT GetTotalHandleCount(void) 
 | ||
| 	{
 | ||
| 		return    (UINT)m_MagicNumbers.count() * ONE_CHUNK_COUNT;
 | ||
| 	}
 | ||
| 
 | ||
| 	inline int GetUserDataSize(void)
 | ||
| 	{
 | ||
| 		return m_nUsedCount * (sizeof(DATA) + ONE_CHUNK_COUNT);
 | ||
| 	}
 | ||
| 
 | ||
| 	inline bool HasUsedHandles( void ) const
 | ||
| 	{ 
 | ||
| 		return ( (GetTotalHandleCount() -GetUsedHandleCount()) >0 ); 
 | ||
| 	}
 | ||
| 	inline VOID GetChunkIdPos(UINT index, UINT &nChunkId, UINT  & nPos)
 | ||
| 	{
 | ||
| 		nPos = index % ONE_CHUNK_COUNT; //取在chunk里的位置; //取在chunk里的位置
 | ||
| 		nChunkId = index / ONE_CHUNK_COUNT; //在第几个chunk
 | ||
| 		
 | ||
| 	}
 | ||
| 	//通过数据指针释放
 | ||
| 	void  ReleaseDataPtr( DATA * pData );
 | ||
| 	
 | ||
| 	//获取第1个有效的数据指针,结果的句柄要放在 hHandle,数据指针放在DATA*
 | ||
| 	DATA * First(HANDLE & hHandle); 
 | ||
| 
 | ||
| 	DATA * Next(HANDLE & hHandle); //hHandle 句柄 下一个有效数据的指针,DATA 为该数据指针
 | ||
| 	
 | ||
| 	//清空内存
 | ||
| 	void Empty(); 
 | ||
| 	
 | ||
| 	// 输出统计信息到文件
 | ||
| 	void dumpToFile()
 | ||
| 	{
 | ||
| 
 | ||
| 	}
 | ||
| 
 | ||
| private:
 | ||
| 	// private types
 | ||
| 	//
 | ||
| 	typedef wylib::container::CBaseList<  wylib::container::CBaseList<DATA> >      UserVec; //数据
 | ||
| 	typedef wylib::container::CBaseList<  wylib::container::CBaseList<HANDLE>  > MagicVec; //handle
 | ||
| 	typedef wylib::container::CBaseList< unsigned int> ChunkFreeCountVec; //每个块还有多少个空闲的句柄
 | ||
| 
 | ||
| 	UINT m_nFirstFreeIndex ; //第1个能用的index,这个用于指向释放了的第1个可用index
 | ||
| 	UINT m_nLastChunkFirstFreeIndex;  //新申请的空闲列表的一个第1个可用的index
 | ||
| 	UINT m_nUsedCount;         //
 | ||
| 	
 | ||
| 	// private data
 | ||
| 	UserVec m_UserData;				// 数据
 | ||
| 	MagicVec  m_MagicNumbers;		 // 存的是每个数据当前使用的句柄
 | ||
| 	ChunkFreeCountVec m_FreeCounts; //每个块有多少个空闲的元素,这个保证每次查找可用的指针最多查找1024个对象
 | ||
| 	const static UINT INVALID_INDEX = ~0 ; //非法的指针
 | ||
| 	//const static  int  ONE_CHUNK_COUNT =1024 ;			//每次申请1024个空间,这个要是2的n次幂
 | ||
| 	//const static  int CHUNK_SHIFT_BIT_COUNT =10;          //移位ONE_CHUNK_COUNT 需要移位运送多少位
 | ||
| 	//const static  int  CHUNK_MASK=0x3ff  ;                  //取在1024块里的位置
 | ||
| };
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| template <typename TAG>
 | ||
| inline bool operator != ( Handle <TAG> l, Handle <TAG> r )
 | ||
| { 
 | ||
| 	return ( l.GetHandle() != r.GetHandle() ); 
 | ||
| }
 | ||
| 
 | ||
| template <typename TAG>
 | ||
| inline bool operator == ( Handle <TAG> l, Handle <TAG> r )
 | ||
| { 
 | ||
| 	return ( l.GetHandle() == r.GetHandle() ); 
 | ||
| }
 | ||
| 
 | ||
| template <typename DATA, typename HANDLE,int ONE_CHUNK_COUNT>
 | ||
| HandleMgr <DATA, HANDLE,ONE_CHUNK_COUNT> :: HandleMgr(LPCTSTR lpszDesc = NULL)
 | ||
| { 
 | ||
| 	m_nFirstFreeIndex = INVALID_INDEX;
 | ||
| 	m_nLastChunkFirstFreeIndex   = INVALID_INDEX;
 | ||
| 	m_nUsedCount =0;
 | ||
| }
 | ||
| template <typename DATA, typename HANDLE, int ONE_CHUNK_COUNT>
 | ||
| void HandleMgr <DATA, HANDLE,ONE_CHUNK_COUNT> ::Empty()
 | ||
| {
 | ||
| 	for(INT_PTR i=0; i<m_UserData.count(); i++)
 | ||
| 	{
 | ||
| 		for(INT_PTR j=0; j< ONE_CHUNK_COUNT ; j ++)
 | ||
| 		{
 | ||
| 			HANDLE hd = m_MagicNumbers[i][j];
 | ||
| 			if(! hd.IsNull() )
 | ||
| 			{
 | ||
| 				DATA *pdata =&( m_UserData[i][j]);
 | ||
| 				if(pdata)
 | ||
| 				{
 | ||
| 					pdata->~DATA();
 | ||
| 				}
 | ||
| 				TRACE(_T("Node not releaseed on HanderMgr destroy,DataSize =%d, hander=%d,index=%d\n"),sizeof(DATA),hd.GetHandle(),hd.GetIndex());
 | ||
| 				//OutputMsg(rmError,_T("Node not releaseed on HanderMgr destroy,DataSize =%d, hander=%d,index=%d"),sizeof(DATA),hd.GetHandle(),hd.GetIndex());
 | ||
| 			}
 | ||
| 		}
 | ||
| 		m_UserData[i].empty();	
 | ||
| 	}
 | ||
| 
 | ||
| 	for(INT_PTR i=0; i<m_UserData.count(); i++)
 | ||
| 	{
 | ||
| 		m_MagicNumbers[i].empty();
 | ||
| 	}
 | ||
| 	m_UserData.empty();
 | ||
| 	m_MagicNumbers.empty();
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| template <typename DATA, typename HANDLE,int ONE_CHUNK_COUNT>
 | ||
| DATA* HandleMgr <DATA, HANDLE,ONE_CHUNK_COUNT> :: Acquire( HANDLE& handle )
 | ||
| {
 | ||
| 	// if free list is empty, add a new one otherwise use first one found 如果空闲列表为空,则新增一个,否则使用第一个可用表项
 | ||
| 	UINT index =INVALID_INDEX;
 | ||
| 	UINT nChunkId =0,nPos=0;
 | ||
| 
 | ||
| 	//如果前面有空闲的位置,优先使用空闲的对象
 | ||
| 	if (m_nFirstFreeIndex != INVALID_INDEX) 
 | ||
| 	{
 | ||
| 		index = m_nFirstFreeIndex;
 | ||
| 		GetChunkIdPos(m_nFirstFreeIndex,nChunkId,nPos);	// 获取当前空闲句柄的位置(在第几块的第几个槽)
 | ||
| 		m_nFirstFreeIndex = INVALID_INDEX;				// 设置当前空闲有效句柄为INVALID_INDEX
 | ||
| 
 | ||
| 		//查找一个空闲的
 | ||
| 		for(INT i =nChunkId ; i < (INT)m_MagicNumbers.count(); i++)	// m_MagicNumbers.count() 是数据块的数目
 | ||
| 		{
 | ||
| 			//只有在这个块有空闲的才去查找,避免了无效的查询,最多1024个
 | ||
| 			bool bFindNextFreeItem = false;
 | ||
| 			INT nFreeCount =  m_FreeCounts[i];
 | ||
| 			if( nFreeCount > 0 )
 | ||
| 			{
 | ||
| 				INT j =0;
 | ||
| 				if( nChunkId == i ) //如果是本块,那么从后一个查起
 | ||
| 				{
 | ||
| 					j = nPos +1;
 | ||
| 					if(nFreeCount ==1) //本块只有1块,那肯定用过了阿
 | ||
| 					{
 | ||
| 						continue;
 | ||
| 					}
 | ||
| 				}
 | ||
| 				CBaseList<HANDLE> & pHandChunk = m_MagicNumbers[i];	// 第i块的句柄数据
 | ||
| 				for (; j < ONE_CHUNK_COUNT; j++)
 | ||
| 				{
 | ||
| 					//HANDLE hTemp = ;
 | ||
| 					if( pHandChunk[j].GetMagic() ==0)
 | ||
| 					{
 | ||
| 						m_nFirstFreeIndex = (i * ONE_CHUNK_COUNT) + j;// 下一个空闲句柄位置
 | ||
| 						bFindNextFreeItem = true;
 | ||
| 						break;
 | ||
| 					}
 | ||
| 				}
 | ||
| 			}
 | ||
| 
 | ||
| 			if (bFindNextFreeItem)
 | ||
| 				break;
 | ||
| 		}
 | ||
| 		//如果其已经到了空闲列表的最后一个了,那么说明前面已经没有可用使用的了
 | ||
| 		if (m_nFirstFreeIndex == m_nLastChunkFirstFreeIndex)
 | ||
| 		{
 | ||
| 			m_nFirstFreeIndex = INVALID_INDEX;
 | ||
| 		}
 | ||
| 	}
 | ||
| 	else
 | ||
| 	{
 | ||
| 		if(m_nLastChunkFirstFreeIndex  == INVALID_INDEX ) //if no chunk
 | ||
| 		{
 | ||
| 			//已经无法申请了
 | ||
| 			UINT nTotalCount =  GetTotalHandleCount();
 | ||
| 			Assert(nTotalCount == GetUsedHandleCount());
 | ||
| 			if ( (unsigned int) nTotalCount >= handle.GetMaxIndex()) return NULL; //已经无法申请了,超过了最大数量
 | ||
| 	
 | ||
| 			CBaseList<DATA> dataChunk;
 | ||
| 			CBaseList<HANDLE> handleChunk;
 | ||
| 			m_UserData.addArray(&dataChunk,1); //添加到列表
 | ||
| 			m_MagicNumbers.addArray(&handleChunk,1);
 | ||
| 			INT_PTR nBackIndex = m_UserData.count();	// m_UserData.count() 是当前数据块的块数目
 | ||
| 			if (nBackIndex <1) return NULL;
 | ||
| 			nBackIndex --;	// 最后一个块的索引			
 | ||
| 			m_UserData[nBackIndex].reserve(ONE_CHUNK_COUNT);	// 保证每个块都是同样长度
 | ||
| 			m_UserData[nBackIndex].trunc(ONE_CHUNK_COUNT);
 | ||
| 		
 | ||
| 			m_MagicNumbers[nBackIndex].reserve(ONE_CHUNK_COUNT);
 | ||
| 			m_MagicNumbers[nBackIndex].trunc(ONE_CHUNK_COUNT);
 | ||
| 			HANDLE *pHandle = m_MagicNumbers[nBackIndex];		// 最后一个句柄块
 | ||
| 			
 | ||
| 			memset(pHandle,0,sizeof(HANDLE) *ONE_CHUNK_COUNT );	// 初始化最后一个句柄块
 | ||
| 			//使用placement new 调用构造函数
 | ||
| 		
 | ||
| 			m_nLastChunkFirstFreeIndex = nTotalCount; //当前的最大数量,指向下一个
 | ||
| 		
 | ||
| 			m_FreeCounts.add(ONE_CHUNK_COUNT); //这个块还有多少个没有使用
 | ||
| 			//m_nAllocedChunkCount++;
 | ||
| 		}
 | ||
| 		if(m_nLastChunkFirstFreeIndex != INVALID_INDEX)
 | ||
| 		{
 | ||
| 			index = m_nLastChunkFirstFreeIndex;
 | ||
| 			m_nLastChunkFirstFreeIndex ++; //指向下一个
 | ||
| 
 | ||
| 			if(m_nLastChunkFirstFreeIndex >= (unsigned) GetTotalHandleCount()) //如果这个块使用完了,就需要重新申请空间了
 | ||
| 			{
 | ||
| 				m_nLastChunkFirstFreeIndex = INVALID_INDEX;
 | ||
| 			}
 | ||
| 		}
 | ||
| 	}
 | ||
| 	
 | ||
| 	
 | ||
| 	//实在是找不到可以使用的了
 | ||
| 	if ( index == INVALID_INDEX)	return NULL;
 | ||
| 	handle.Init( index );
 | ||
| 	GetChunkIdPos(index,nChunkId,nPos);
 | ||
| 	unsigned int nFreeCount =  m_FreeCounts[nChunkId];
 | ||
| 	if (nChunkId < (UINT)m_MagicNumbers.count() && nFreeCount >0 )
 | ||
| 	{
 | ||
| 		m_MagicNumbers[nChunkId][nPos] =handle;
 | ||
| 	}
 | ||
| 	else
 | ||
| 	{		
 | ||
| 		return NULL;
 | ||
| 	}
 | ||
| 
 | ||
| 	m_FreeCounts[nChunkId]--; //这个列表空闲的数量 	
 | ||
| 
 | ||
| 	DATA *pData = &(m_UserData[nChunkId][nPos]);
 | ||
| 	new(pData)DATA();//placement new
 | ||
| 	m_nUsedCount++;
 | ||
| 	//m_nUsedHdlCount++;
 | ||
| 	//if (m_nUsedHdlCount > m_nMaxUsedHandleCount)
 | ||
| 	//	m_nMaxUsedHandleCount = m_nUsedHdlCount;
 | ||
| 	return pData;
 | ||
| }
 | ||
| 
 | ||
| template <typename DATA, typename HANDLE,int ONE_CHUNK_COUNT>
 | ||
| void HandleMgr <DATA, HANDLE,ONE_CHUNK_COUNT> :: ReleaseDataPtr( DATA * pData )
 | ||
| {
 | ||
| 	UINT_PTR count =m_UserData.count();
 | ||
| 	SIZE_T nChunkSize = ONE_CHUNK_COUNT * sizeof(DATA);  //每一块Chunk的大小,每次申请1024个
 | ||
| 	UINT_PTR nEndIndex = ONE_CHUNK_COUNT -1; //1023
 | ||
| 	for (UINT_PTR i= 0;i< count; i++)
 | ||
| 	{
 | ||
| 		DATA * pStart = &m_UserData[i][0];
 | ||
| 		DATA * pEnd =  &m_UserData[i][nEndIndex];
 | ||
| 		
 | ||
| 		INT_PTR nDataIndex = pData -pStart;  //第多少个数据
 | ||
| 		if(nDataIndex >= 0 && pData <=  pEnd) //找到了这个内存块
 | ||
| 		{
 | ||
| 			INT_PTR nByteDis = (char *)pData -  (char *)pStart;
 | ||
| 			if( nByteDis  % sizeof(DATA) != 0) //内存长度错误
 | ||
| 			{
 | ||
| 				return; 
 | ||
| 			}
 | ||
| 			Release( m_MagicNumbers[i][nDataIndex] );
 | ||
| 			return;
 | ||
| 		}
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| template <typename DATA, typename HANDLE,int ONE_CHUNK_COUNT>
 | ||
| void HandleMgr <DATA, HANDLE,ONE_CHUNK_COUNT> :: Release( HANDLE handle )
 | ||
| {
 | ||
| 	// which one? 哪一个
 | ||
| 	if ( handle.IsNull() )return;
 | ||
| 	unsigned int index = handle.GetIndex();
 | ||
| 	UINT nChunkId =0,nPos=0;
 | ||
| 	GetChunkIdPos(index,nChunkId,nPos);
 | ||
| 
 | ||
| 	if( nChunkId  >= (UINT)m_MagicNumbers.count() ) return ; //有问题,已经超过了
 | ||
| 	if (m_MagicNumbers[nChunkId][nPos].GetMagic() != handle.GetMagic()) return; //重复释放
 | ||
| 
 | ||
| 	// ok remove it - tag as unused and add to free list 可以删除了--表及其没有使用并加到空闲列表
 | ||
| 	
 | ||
| 	if (index < m_nFirstFreeIndex )
 | ||
| 	{
 | ||
| 		m_nFirstFreeIndex = index;
 | ||
| 	}
 | ||
| 	HANDLE hTemp;
 | ||
| 	m_MagicNumbers[nChunkId][nPos] =hTemp;
 | ||
| 	
 | ||
| 
 | ||
| 	//调用析构函数
 | ||
| 	DATA *pdata =&( m_UserData[nChunkId][nPos]);
 | ||
| 	if(pdata)
 | ||
| 	{
 | ||
| 		pdata->~DATA();
 | ||
| 	}
 | ||
| 
 | ||
| 	m_FreeCounts[nChunkId] ++; //这个块的空闲的个数 -1
 | ||
| 	m_nUsedCount--;	
 | ||
| 	//m_nUsedHdlCount--;
 | ||
| }
 | ||
| 
 | ||
| template<typename DATA, typename HANDLE, int ONE_CHUNK_COUNT>
 | ||
| bool HandleMgr <DATA, HANDLE,ONE_CHUNK_COUNT> :: ReNew( HANDLE &handle)
 | ||
| {
 | ||
| 	if (handle.IsNull())
 | ||
| 		return false;
 | ||
| 
 | ||
| 	// check handle validity
 | ||
| 	unsigned int index = handle.GetIndex();
 | ||
| 	UINT nChunkId =0,nPos=0;
 | ||
| 	GetChunkIdPos(index,nChunkId,nPos);
 | ||
| 	if (nChunkId > (UINT)m_MagicNumbers.count() || m_MagicNumbers[nChunkId][nPos].GetMagic() != handle.GetMagic())
 | ||
| 		return false;
 | ||
| 
 | ||
| 	handle.updateMagic();
 | ||
| 	m_MagicNumbers[nChunkId][nPos] = handle;
 | ||
| 	return true;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| template <typename DATA, typename HANDLE,int ONE_CHUNK_COUNT>
 | ||
| inline DATA* HandleMgr <DATA, HANDLE,ONE_CHUNK_COUNT>
 | ||
| 	:: GetDataPtr( HANDLE handle )
 | ||
| {
 | ||
| 	if ( handle.IsNull() ) return ( 0 );
 | ||
| 	unsigned int index = handle.GetIndex();
 | ||
| 	UINT nChunkId =0,nPos=0;
 | ||
| 	GetChunkIdPos(index,nChunkId,nPos);
 | ||
| 
 | ||
| 	// check handle validity - $ this check can be removed for speed 检查句柄有效性-为提供性能可以去掉这个检查
 | ||
| 	// if you can assume all handle references are always valid. 如果你假设索引句柄解引用都总是有效
 | ||
| 
 | ||
| 	if( nChunkId  >=(UINT)m_MagicNumbers.count()) return NULL; //有问题,
 | ||
| 	if (m_MagicNumbers[nChunkId][nPos].GetMagic() != handle.GetMagic()) 
 | ||
| 		return NULL; //重复释放
 | ||
| 
 | ||
| 	return (& m_UserData[nChunkId][nPos] );
 | ||
| }
 | ||
| 
 | ||
| template <typename DATA, typename HANDLE,int ONE_CHUNK_COUNT>
 | ||
| inline const DATA* HandleMgr <DATA, HANDLE,ONE_CHUNK_COUNT>
 | ||
| 	:: GetDataPtr( HANDLE handle ) const
 | ||
| {
 | ||
| 	// this lazy cast is ok - non-const version does not modify anything
 | ||
| 	typedef HandleMgr <DATA, HANDLE> ThisType;
 | ||
| 	return ( const_cast <ThisType*> ( this )->GetDataPtr( handle ) );
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| //获取第1个有效的数据指针,结果的句柄要放在 hHandle,数据指针放在DATA*
 | ||
| template <typename DATA, typename HANDLE,int ONE_CHUNK_COUNT>
 | ||
|  DATA* HandleMgr <DATA, HANDLE,ONE_CHUNK_COUNT>
 | ||
|  ::First(HANDLE & hHandle)
 | ||
| {
 | ||
| 	
 | ||
| 	INT_PTR count=	m_FreeCounts.count();
 | ||
| 	for(int i=0; i< count; i++)
 | ||
| 	{
 | ||
| 		if(ONE_CHUNK_COUNT- m_FreeCounts[i] >0 ) //如果一个块里有数据,那么就在这个块里找
 | ||
| 		{
 | ||
| 			
 | ||
| 			for(INT_PTR j=0; j< ONE_CHUNK_COUNT; j++)
 | ||
| 			{
 | ||
| 				if(m_MagicNumbers[i][j] != 0)
 | ||
| 				{
 | ||
| 					hHandle = m_MagicNumbers[i][j];
 | ||
| 					return &m_UserData[i][j];
 | ||
| 				}
 | ||
| 			}
 | ||
| 		}
 | ||
| 	}
 | ||
| 	return NULL;
 | ||
| }
 | ||
| 
 | ||
| //hHandle 句柄 下一个有效数据的指针,DATA 为该数据指针
 | ||
|  template <typename DATA, typename HANDLE,int ONE_CHUNK_COUNT>
 | ||
|  DATA* HandleMgr <DATA, HANDLE,ONE_CHUNK_COUNT>
 | ||
| :: Next(HANDLE & hHandle)
 | ||
| {
 | ||
| 	if(hHandle ==0) return NULL; //压根就没有输入
 | ||
| 	UINT index = hHandle.GetIndex();
 | ||
| 	UINT nChunkId =0,nPos=0;
 | ||
| 	GetChunkIdPos(index,nChunkId,nPos);
 | ||
| 
 | ||
| 	for(INT_PTR i =nChunkId ; i < m_MagicNumbers.count(); i++)
 | ||
| 	{
 | ||
| 		//只有在这个块有空闲的才去查找,避免了无效的查询,最多1024个
 | ||
| 		INT_PTR nFreeCount =  m_FreeCounts[i];
 | ||
| 		if( ONE_CHUNK_COUNT- nFreeCount >0   )
 | ||
| 		{
 | ||
| 			INT_PTR j =0;
 | ||
| 			if( nChunkId == i ) //如果是本块,那么从后一个查起
 | ||
| 			{
 | ||
| 				j = nPos +1;
 | ||
| 				if(nFreeCount ==1) //本块只有1块,那肯定用过了阿
 | ||
| 				{
 | ||
| 					continue;
 | ||
| 				}
 | ||
| 			}
 | ||
| 			CBaseList<HANDLE> & pHandChunk = m_MagicNumbers[i];
 | ||
| 			for (; j < ONE_CHUNK_COUNT; j++)
 | ||
| 			{
 | ||
| 				//HANDLE hTemp = ;
 | ||
| 				if( pHandChunk[j].GetMagic() !=0)
 | ||
| 				{
 | ||
| 					hHandle = pHandChunk[j];
 | ||
| 					return  &m_UserData[i][j];
 | ||
| 				}
 | ||
| 			}
 | ||
| 		}
 | ||
| 	}
 | ||
| 	return NULL;
 | ||
| }
 |