Files
Sun1602/Utility/ObjKeyGenerator.h
2022-10-26 12:25:11 +08:00

388 lines
10 KiB
C++

#pragma once
#ifndef UTILITY_OBJKEY_GENERATOR_H
#define UTILITY_OBJKEY_GENERATOR_H
#include <UtilityCommon.h>
#include <chunk_stl.h>
#pragma pack(push)
#pragma pack()
namespace util {
;
//==================================================================================================
// <CObjKeyGenerator>
// - Object들에 Key를 발급하고 회수하는 매니저
// <History>
// - 040906 : (ver1.0) Created
// - 080519 : (ver1.1) DataStructure Changed & Bug Fix (by MjKim)
// - 080520 : (ver1.2) Server Support by replacing datastructure (by Waverix)
// - ver1.1을 Server에서 사용하는데는 위험부담이 높아지는 관계로 자료구조 변경 (1.1의 목적도 반영)
// <Used Version>
// - 0x0100 - general
// - 0x0110
// - 0x0120
// - 0x0130 - (ver1.3) change to an enhanced 'ReserveKey' to support client local handling
//
#define __OBJKEYGEN_VERSION_CTRL 0x0130
//
#if __OBJKEYGEN_VERSION_CTRL == 0x0130
//==================================================================================================
// version 0.1.3.0
namespace internal {
;
class ObjectKeyGeneratorBase
{
public:
typedef ulong key_type;
//static const key_type kMaxKeyBandwidth = (USHRT_MAX << 2); // (ULONG_MAX >> 2);
static const key_type kMaxKeyBandwidth = (ULONG_MAX >> 2); // (ULONG_MAX >> 2);
static const key_type kEmptyKey = 0;
//
ObjectKeyGeneratorBase();
ObjectKeyGeneratorBase(key_type start_key, key_type end_key);
~ObjectKeyGeneratorBase();
//
bool Create(key_type start_key, key_type end_key);
key_type GetKey();
bool RestoreKey(key_type key);
bool IsExistKey(key_type key) const;
bool ReserveKey(key_type key);
bool IsEmpty() const;
size_t GetSize() const;
private:
static const BOOLEAN kColorOfIssued = true;
static const BOOLEAN kColorOfFree = !kColorOfIssued;
#pragma pack(push, 1)
struct AlignNode { BOOLEAN color_; };
#pragma pack(pop)
//
typedef STLX_DEQUE<AlignNode*> KeySet; // Free Key Set
//
// data fields...
bool initialized_;
key_type lower_bound_;
key_type upper_bound_;
int number_of_free_;
AlignNode* total_array_;
KeySet free_key_set_;
};
//--------------------------------------------------------------------------------------------------
// implements
inline ObjectKeyGeneratorBase::ObjectKeyGeneratorBase()
: initialized_(false),
lower_bound_(0),
upper_bound_(0),
number_of_free_(0),
total_array_(NULL)
{
}
inline ObjectKeyGeneratorBase::ObjectKeyGeneratorBase(key_type start_key, key_type end_key)
{
Create(start_key, end_key);
}
inline bool ObjectKeyGeneratorBase::IsExistKey(key_type key) const
{
if (lower_bound_ <= key && key < upper_bound_)
{
const key_type offset = key - lower_bound_;
const AlignNode* align = &total_array_[offset];
return (kColorOfFree == align->color_);
}
return false;
}
inline bool ObjectKeyGeneratorBase::IsEmpty() const
{
return number_of_free_ <= 0;
}
inline size_t ObjectKeyGeneratorBase::GetSize() const
{
return number_of_free_;
}
}; //end of nested namespace 'internal'
//==================================================================================================
//
template<typename _KEYTYPE = DWORD>
class CObjKeyGenerator : public internal::ObjectKeyGeneratorBase
{
public:
typedef _KEYTYPE key_type;
// acceptable types = { uint8_t, uint16_t, uint32_t, ulong(DWORD) }
BOOST_STATIC_ASSERT(\
boost::is_integral<key_type>::value &&
sizeof(key_type) <= sizeof(typename internal::ObjectKeyGeneratorBase::key_type) &&
static_cast<key_type>(-1) > 0);
//
CObjKeyGenerator();
CObjKeyGenerator(key_type start_key, key_type end_key);
~CObjKeyGenerator();
//
bool Create(key_type start_key, key_type end_key);
key_type GetKey();
bool RestoreKey(key_type key);
bool IsExistKey(key_type key) const;
bool ReserveKey(key_type key);
bool IsEmpty() const;
size_t GetSize() const;
};
//--------------------------------------------------------------------------------------------------
// implements
template<typename _KEYTYPE>
inline CObjKeyGenerator<_KEYTYPE>::CObjKeyGenerator()
{
}
template<typename _KEYTYPE>
inline CObjKeyGenerator<_KEYTYPE>::CObjKeyGenerator(key_type start_key, key_type end_key)
{
ObjectKeyGeneratorBase::Create(start_key, end_key);
}
template<typename _KEYTYPE>
inline bool CObjKeyGenerator<_KEYTYPE>::Create(key_type start_key, key_type end_key)
{
return ObjectKeyGeneratorBase::Create(start_key, end_key);
}
template<typename _KEYTYPE>
inline CObjKeyGenerator<_KEYTYPE>::~CObjKeyGenerator()
{
}
template<typename _KEYTYPE>
inline typename CObjKeyGenerator<_KEYTYPE>::key_type
CObjKeyGenerator<_KEYTYPE>::GetKey()
{
return static_cast<key_type>(ObjectKeyGeneratorBase::GetKey());
}
template<typename _KEYTYPE>
inline bool CObjKeyGenerator<_KEYTYPE>::RestoreKey(key_type key)
{
return ObjectKeyGeneratorBase::RestoreKey(key);
}
template<typename _KEYTYPE>
inline bool CObjKeyGenerator<_KEYTYPE>::IsExistKey(key_type key) const
{
return ObjectKeyGeneratorBase::IsExistKey(key);
}
template<typename _KEYTYPE>
inline bool CObjKeyGenerator<_KEYTYPE>::ReserveKey(key_type key)
{
return ObjectKeyGeneratorBase::ReserveKey(key);
}
template<typename _KEYTYPE>
inline bool CObjKeyGenerator<_KEYTYPE>::IsEmpty() const
{
return ObjectKeyGeneratorBase::IsEmpty();
}
template<typename _KEYTYPE>
inline size_t CObjKeyGenerator<_KEYTYPE>::GetSize() const
{
return ObjectKeyGeneratorBase::GetSize();
}
//
//==================================================================================================
#elif __OBJKEYGEN_VERSION_CTRL == 0x0120
//==================================================================================================
// version 0.1.2.0
template<typename _KEYTYPE = DWORD>
class CObjKeyGenerator
{
public: CObjKeyGenerator( VOID );
CObjKeyGenerator( const _KEYTYPE startKey, const _KEYTYPE endKey );
~CObjKeyGenerator( VOID );
public:
//─────────────────────────────────────────
// <INTERFACEs>
public: VOID Create( const _KEYTYPE startKey, const _KEYTYPE endKey );
_KEYTYPE GetKey( VOID );
VOID RestoreKey( const _KEYTYPE key );
BOOL IsExistKey( const _KEYTYPE key );
BOOL ReserveKey( const _KEYTYPE key );
BOOL IsEmpty( VOID );
SIZE_T GetSize( VOID );
private:
static const BOOLEAN COLOR_ISSUE = TRUE;
static const BOOLEAN COLOR_FREE = FALSE;
struct sALIGN { _KEYTYPE KEY; BOOLEAN COLOR; };
typedef STLX_DEQUE<_KEYTYPE> KeySet; // Free Key Set
typedef STLX_VECTOR<sALIGN> TotalSet; // Set for total managed key
private: _KEYTYPE m_Lowerbound;
_KEYTYPE m_Upperbound;
KeySet m_keySet;
TotalSet m_TotalKey;
};
template<typename _KEYTYPE>
CObjKeyGenerator<_KEYTYPE>::CObjKeyGenerator( VOID )
{
m_Lowerbound = m_Upperbound = 0;
}
template<typename _KEYTYPE>
CObjKeyGenerator<_KEYTYPE>::CObjKeyGenerator( const _KEYTYPE startKey, const _KEYTYPE endKey )
{
Create( startKey, endKey );
}
template<typename _KEYTYPE>
VOID CObjKeyGenerator<_KEYTYPE>::Create( const _KEYTYPE startKey, const _KEYTYPE endKey )
{
ASSERT( (startKey < endKey) && m_keySet.empty() );
m_Lowerbound = startKey;
m_Upperbound = endKey + 1 ; // [lb, endKey] -> [lb, up)
const _KEYTYPE range = m_Upperbound-m_Lowerbound;
// deque는 reserve가 없어용
m_TotalKey.reserve( range );
sALIGN alignS = { 0, COLOR_FREE };
for( _KEYTYPE key=m_Lowerbound ; key<m_Upperbound ; ++key )
{
alignS.KEY = key;
m_TotalKey.push_back( alignS );
m_keySet.push_back( key );
}
}
template<typename _KEYTYPE>
CObjKeyGenerator<_KEYTYPE>::~CObjKeyGenerator( VOID )
{
m_Lowerbound = m_Upperbound = 0;
}
template<typename _KEYTYPE>
_KEYTYPE CObjKeyGenerator<_KEYTYPE>::GetKey( VOID )
{
if( m_keySet.empty() )
{
ASSERT( !"할당할 수 있는 키가 없습니다." );
return (_KEYTYPE)0;
}
KeySet::iterator it = m_keySet.begin();
const _KEYTYPE issue_key = *it;
const _KEYTYPE index = issue_key-m_Lowerbound;
sALIGN& rAlign = m_TotalKey[index];
rAlign.COLOR = COLOR_ISSUE;
m_keySet.pop_front();
return issue_key;
}
template<typename _KEYTYPE>
VOID CObjKeyGenerator<_KEYTYPE>::RestoreKey( const _KEYTYPE key )
{
if( m_Lowerbound<=key && key<m_Upperbound )
{
const _KEYTYPE index = key-m_Lowerbound;
sALIGN& rAlign = m_TotalKey[index];
if( COLOR_ISSUE == rAlign.COLOR )
{
rAlign.COLOR = COLOR_FREE;
m_keySet.push_back( key );
return;
}
ASSERT( (COLOR_ISSUE == rAlign.COLOR) ); // 이미 반환되거나...
return;
}
ASSERT( (m_Lowerbound<=key && key<m_Upperbound) ); // 잘못된 키
}
template<typename _KEYTYPE>
BOOL CObjKeyGenerator<_KEYTYPE>::IsExistKey( const _KEYTYPE key )
{
if( m_Lowerbound<=key && key<m_Upperbound )
{
const _KEYTYPE index = key-m_Lowerbound;
sALIGN& rAlign = m_TotalKey[index];
return ( COLOR_FREE == rAlign.COLOR );
}
return FALSE;
}
// (NOTE) 이건 특별한 일 없으면 사용하지 않는 것이 좋다.
template<typename _KEYTYPE>
BOOL CObjKeyGenerator<_KEYTYPE>::ReserveKey( const _KEYTYPE key )
{
if( m_Lowerbound<=key && key<m_Upperbound )
{
const _KEYTYPE index = key-m_Lowerbound;
sALIGN& rAlign = m_TotalKey[index];
if( COLOR_FREE == rAlign.COLOR )
{
rAlign.COLOR = COLOR_ISSUE;
KeySet::iterator itfind = find( m_keySet.begin(), m_keySet.end(), key );
if( itfind != m_keySet.end() )
m_keySet.erase( itfind );
return TRUE;
}
ASSERT( (COLOR_FREE == rAlign.COLOR) );
}
ASSERT( (m_Lowerbound<=key && key<m_Upperbound) );
return FALSE;
}
template<typename _KEYTYPE>
BOOL CObjKeyGenerator<_KEYTYPE>::IsEmpty( VOID )
{
return ( m_keySet.empty() );
}
template<typename _KEYTYPE>
SIZE_T CObjKeyGenerator<_KEYTYPE>::GetSize( VOID )
{
return m_keySet.size();
}
//==================================================================================================
#else //__OBJKEYGEN_VERSION_CTRL < 0x0120
; //
#endif
}; // End of Namespace Util
#pragma pack(pop)
#endif //UTILITY_OBJKEY_GENERATOR_H