Files
Sun1602/SUN3DEngine/include/ProgramCommon/wzhandlemanager.h
T
2022-10-26 12:25:11 +08:00

324 lines
7.2 KiB
Objective-C

// wzhandlemanager.h
#ifndef _PROGRAMCOMMON_WZHANDLEMANAGER_H_
#define _PROGRAMCOMMON_WZHANDLEMANAGER_H_
#include "wzarray.h"
#define MAX_NUM_HANDLES 65535
#define MAX_MAGIC_NO 65534
#define MIN_NUM_FOR_CLEAR 1000
struct St_Handle
{
union
{
struct
{
unsigned short m_index;
unsigned short m_magicNo;
};
HANDLE m_handle;
};
};
//------------------------------------------------------------------------------
/**
@class CWzHandleManager
*/
template <class T>
class CWzHandleManager
{
public:
// 생성자/소멸자
CWzHandleManager( void );
virtual ~CWzHandleManager( void );
// 초기화
void Clear( void );
// 데이타 추가(핸들 반환)
HANDLE Add( const T& data );
// 데이타 제거
BOOL Release( HANDLE handle );
// 데이타 얻기
const T& GetData( HANDLE handle ) const;
// 데이타 바꾸기
BOOL Replace( HANDLE handle, const T& data );
// 전체 데이타 수
int Idx_GetCount( void ) const;
// 인덱스로 데이타 얻기
const T& Idx_GetData( int index ) const;
// 인덱스로 매직 넘버 얻기
unsigned short Idx_GetMagicNumber( int index ) const;
// 인덱스로 데이타 해제
void Idx_Release( int index );
// 유효한 핸들인가?
BOOL IsValidHandle( HANDLE handle ) const;
protected:
// xxx: 구차하게 이런 변수를 만들고 싶진 않지만
// 기존에 이미 쓰레기 값을 리턴해야 하는 경우가 있기 때문에
// 차라리 이 방법이 좋은 것 같아 이렇게 간다.
static T m_dummyData;
static T m_nullData;
protected:
CWzArray<T> m_dataList;
CWzArray<unsigned short> m_magicNoList;
private:
CWzArray<unsigned short> m_freeIdxList;
unsigned short m_numFreeIdx;
unsigned short m_maxIndex;
unsigned short m_newMagicNo;
};
template <class T>
T CWzHandleManager<T>::m_dummyData;
template <class T>
T CWzHandleManager<T>::m_nullData;
//------------------------------------------------------------------------------
/**
- m_newMagicNo( 1 )
- 매직 넘버가 1부터 시작한다는 것을 강조하기 위해 1로 초기화 함
*/
template <class T>
CWzHandleManager<T>::CWzHandleManager( void )
{
// xxx: T가 뭐가 될 지 모르는 상황에서 memset을 한다는 자체가
// 굉장히 위험하지만, 기존에 이미 그런 상황이 벌어졌기 때문에
// 차라리 이 방법이 최선인 것 같아, 멤버 변수로 두고 여기서 초기화 함
memset( &m_nullData, 0, sizeof( T ) );
memset( &m_dummyData, 0, sizeof( T ) );
// 버퍼 생성
//m_dataList.EnlargeSize( MAX_NUM_HANDLES );
//m_magicNoList.EnlargeSize( MAX_NUM_HANDLES );
//m_freeIdxList.EnlargeSize( MAX_NUM_HANDLES );
// 초기화
Clear();
}
//------------------------------------------------------------------------------
/**
*/
template <class T>
CWzHandleManager<T>::~CWzHandleManager( void )
{
// empty
}
//------------------------------------------------------------------------------
/**
*/
template <class T>
void CWzHandleManager<T>::Clear( void )
{
m_numFreeIdx = 0;
m_maxIndex = 0;
m_newMagicNo = 1;
m_dataList.Clear();
m_magicNoList.Clear();
m_freeIdxList.Clear();
}
//------------------------------------------------------------------------------
/**
데이타 추가
- index : 0 ~ 65534
- magic No : 1 ~ 65534
*/
template <class T>
HANDLE CWzHandleManager<T>::Add( const T& data )
{
St_Handle sth;
// 해제된 인덱스가 있는 경우
if( m_numFreeIdx > 0 )
{
sth.m_index = m_freeIdxList.Get( --m_numFreeIdx );
}
else
{
// 새로 할당할 경우
if( m_maxIndex >= MAX_NUM_HANDLES )
{
return INVALID_HANDLE_VALUE;
}
sth.m_index = m_maxIndex++;
}
// 매직 넘버
if( m_newMagicNo > MAX_MAGIC_NO )
{
// 매직 넘버는 0 도 안되고 0xFFFF 도 안되야 정상인지 체크할 수 있다.
m_newMagicNo = 1;
}
sth.m_magicNo = m_newMagicNo++;
// 정보 저장
m_dataList.Set( sth.m_index, data );
m_magicNoList.Set( sth.m_index, sth.m_magicNo );
return sth.m_handle;
}
//------------------------------------------------------------------------------
/**
*/
template <class T>
BOOL CWzHandleManager<T>::Release( HANDLE handle )
{
// 핸들 유효성 검사
if( !IsValidHandle( handle ) )
{
return FALSE;
}
St_Handle sth;
sth.m_handle = handle;
// 매직 넘버 초기화
m_magicNoList.Set( sth.m_index, 0 );
// xxx : 아~ 골 때리네;
// 하튼 맘에 안들지만 일단은 이렇게 가자.
// 매직 넘버가 0인 것은 쓰레기 값인데 외부에서 이걸 무시하고
// Idx_ 계열 함수를 통해 데이타를 얻는 경우가 있어서,
// 어쩔 수 없이 여기서 초기화를 해 준다.
m_dataList.Set( sth.m_index, m_nullData );
// 해제 인덱스 리스트에 추가
WzAssert( m_numFreeIdx < m_maxIndex );
m_freeIdxList.Set( m_numFreeIdx, sth.m_index );
++m_numFreeIdx;
// 해제된 수와 최대 인덱스가 크거나 같은 경우, 초기화
// 단, 너무 자주 호출되는 것을 막기 위해 최소한의 값을 둔다.
if( m_numFreeIdx > MIN_NUM_FOR_CLEAR && m_numFreeIdx >= m_maxIndex )
{
Clear();
}
return TRUE;
}
//------------------------------------------------------------------------------
/**
*/
template <class T>
const T& CWzHandleManager<T>::GetData( HANDLE handle ) const
{
if( !IsValidHandle( handle ) )
{
return m_dummyData;
}
St_Handle sth;
sth.m_handle = handle;
return m_dataList.Get( sth.m_index );
}
//------------------------------------------------------------------------------
/**
*/
template <class T>
BOOL CWzHandleManager<T>::Replace( HANDLE handle, const T& data )
{
if( !IsValidHandle( handle ) )
{
return FALSE;
}
St_Handle sth;
sth.m_handle = handle;
m_dataList.Set( sth.m_index, data );
return TRUE;
}
//------------------------------------------------------------------------------
/**
*/
template <class T>
BOOL CWzHandleManager<T>::IsValidHandle( HANDLE handle ) const
{
St_Handle sth;
sth.m_handle = handle;
// 유효 핸들 여부, 매직 넘버 체크
if( handle == INVALID_HANDLE_VALUE || sth.m_magicNo == 0 )
{
return FALSE;
}
// 해당 인덱스의 매직 넘버를 얻고
unsigned short magicNo = m_magicNoList.Get( sth.m_index );
// 주어진 핸들의 매직넘버와 저장된 매직 넘버와 비교
if( sth.m_magicNo != magicNo )
{
return FALSE;
}
return TRUE;
}
//------------------------------------------------------------------------------
/**
*/
template <class T>
int CWzHandleManager<T>::Idx_GetCount( void ) const
{
return m_dataList.GetCount();
}
//------------------------------------------------------------------------------
/**
*/
template <class T>
const T& CWzHandleManager<T>::Idx_GetData( int index ) const
{
return m_dataList.Get( index );
}
//------------------------------------------------------------------------------
/**
*/
template <class T>
unsigned short CWzHandleManager<T>::Idx_GetMagicNumber( int index ) const
{
return m_magicNoList.Get( index );
}
//------------------------------------------------------------------------------
/**
*/
template <class T>
void CWzHandleManager<T>::Idx_Release( int index )
{
St_Handle sth;
sth.m_index = index;
sth.m_magicNo = Idx_GetMagicNumber( index );
Release( sth.m_handle );
}
#endif // _PROGRAMCOMMON_WZHANDLEMANAGER_H_