/*---------------------------------------------------------------------------* Project: Horizon File: fslow_HandleTable.h Copyright 2010 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Rev: 20673 $ *---------------------------------------------------------------------------*/ #ifndef NN_FSLOW_FSLOW_HANDLETABLE_H_ #define NN_FSLOW_FSLOW_HANDLETABLE_H_ #include #include namespace nn { namespace fslow { typedef nn::util::Int64 HandleValue; /*---------------------------------------------------------------------------* * ファイルハンドル * - 固定値, 有効フラグ, インクリメント可能 *---------------------------------------------------------------------------*/ class Handle { protected: HandleValue m_Data; static const bit32 FIXED_VALUE_MASK = 0x0FF; static const bit32 VALID_FLAG_MASK = 0x100; static const bit32 INCREMENT_VALUE = 0x200; public: Handle() { m_Data.lo = 0; m_Data.hi = 0; } Handle(bit8 fixedValue) { m_Data.lo = fixedValue + INCREMENT_VALUE; m_Data.hi = 0; } Handle(const HandleValue& value) { m_Data.lo = value.lo; m_Data.hi = value.hi; } void Initialize(bit8 fixedValue) { NN_TASSERT_(!IsInitialized()); m_Data.lo = fixedValue + INCREMENT_VALUE; } void Finalize() { m_Data.lo = 0; m_Data.hi = 0; } void Validate() { NN_TASSERT_(IsInitialized()); m_Data.lo |= VALID_FLAG_MASK; } void Invalidate() { NN_TASSERT_(IsInitialized()); m_Data.lo &= ~VALID_FLAG_MASK; Increment(); } bit8 GetFixedValue() const { return static_cast(m_Data.lo & FIXED_VALUE_MASK); } bool IsInitialized() const { return (m_Data.lo != 0) || (m_Data.hi != 0); } bool IsValid() const { return (m_Data.lo & VALID_FLAG_MASK) != 0; } operator HandleValue() const { return m_Data; } operator const HandleValue&() const { return m_Data; } operator bool() const { return IsValid(); } bool operator!() const { return !IsValid(); } bool operator==(const HandleValue& rhs) const { return (m_Data.lo == rhs.lo) && (m_Data.hi == rhs.hi); } bool operator!=(const HandleValue& rhs) const { return (m_Data.lo != rhs.lo) || (m_Data.hi != rhs.hi); } protected: void Increment() { m_Data.lo += INCREMENT_VALUE; if (((m_Data.lo & ~FIXED_VALUE_MASK) == 0) && (++m_Data.hi == 0)) { m_Data.lo += INCREMENT_VALUE; } } }; /*---------------------------------------------------------------------------* * ハンドルテーブルエントリ *---------------------------------------------------------------------------*/ template class HandleTableEntry { public: HandleTableEntry() {} HandleTableEntry(bit8 fixedValue) { Initialize(fixedValue); } ~HandleTableEntry() {} // 初期化 void Initialize(bit8 fixedValue) { NN_TASSERT_(!IsInitialized()); m_Handle.Initialize(fixedValue); } // このエントリに紐付けるオブジェクトを登録 const HandleValue& Register(const T& object) { NN_TASSERT_(!m_Handle.IsValid()); m_Object = object; m_Handle.Validate(); return m_Handle; } // 登録を解除(ハンドルを無効にする) void Unregister() { NN_TASSERT_(m_Handle.IsValid()); m_Handle.Invalidate(); } const HandleValue& GetHandle() const { return m_Handle; } const T& GetObject() const { return m_Object; } bool IsInitialized() const { return m_Handle.IsInitialized(); } bool IsValid() const { return m_Handle.IsValid(); } bool HasHandle(HandleValue value) const { return IsValid() && (m_Handle == value); } private: Handle m_Handle; T m_Object; }; /*---------------------------------------------------------------------------* * ハンドルテーブル *---------------------------------------------------------------------------*/ template class HandleTable { typedef HandleTableEntry TEntry; public: HandleTable() {} HandleTable(nn::WithInitialize) { Initialize(); } ~HandleTable() {} // 初期化 // - ハンドルの固有値としてインデックスを渡す void Initialize() { for(s32 i = 0; i < TNumEntry; ++i) { m_Entry[i].Initialize(i); } } // オブジェクトの登録 const HandleValue& Register(const T& object) { TEntry* pEntry = FindFreeEntry(); NN_TASSERT_(pEntry); return pEntry->Register(object); } // オブジェクトを削除 void Unregister(const HandleValue& value) { TEntry* pEntry = const_cast(FindEntryFromHandle(value)); NN_TASSERT_(pEntry); pEntry->Unregister(); } // 指定したハンドルに紐付いているオブジェクトを返す const T& GetObject(const HandleValue& value) const { const TEntry* pEntry = FindEntryFromHandle(value); NN_TASSERT_(pEntry); return pEntry->GetObject(); } bool TryGetObject(T* pObject, const HandleValue& value) const { const TEntry* pEntry = FindEntryFromHandle(value); if(pEntry) { *pObject = pEntry->GetObject(); return true; } return false; } private: TEntry m_Entry[TNumEntry]; // 未使用のエントリを探す TEntry* FindFreeEntry() { for(s32 i = 0; i < TNumEntry; ++i) { if(!m_Entry[i].IsValid()) { return m_Entry + i; } } return 0; } // 指定したハンドルが登録されているエントリを探す const TEntry* FindEntryFromHandle(const HandleValue& value) const { // 固定値の部分にインデックスを入れているので利用する Handle handle(value); s32 index = handle.GetFixedValue(); if(index < TNumEntry) { return m_Entry[index].HasHandle(value) ? (m_Entry + index) : 0; } return 0; } }; }} #endif // #ifndef NN_FSLOW_FSLOW_HANDLETABLE_H_