1 /*---------------------------------------------------------------------------* 2 Project: Horizon 3 File: fslow_HandleTable.h 4 5 Copyright 2010 Nintendo. All rights reserved. 6 7 These coded instructions, statements, and computer programs contain 8 proprietary information of Nintendo of America Inc. and/or Nintendo 9 Company Ltd., and are protected by Federal copyright law. They may 10 not be disclosed to third parties or copied or duplicated in any form, 11 in whole or in part, without the prior written consent of Nintendo. 12 13 $Rev: 20673 $ 14 *---------------------------------------------------------------------------*/ 15 16 #ifndef NN_FSLOW_FSLOW_HANDLETABLE_H_ 17 #define NN_FSLOW_FSLOW_HANDLETABLE_H_ 18 19 #include <nn.h> 20 #include <nn/util/util_Int64.h> 21 22 23 namespace nn { namespace fslow { 24 25 typedef nn::util::Int64<bit64> HandleValue; 26 27 /*---------------------------------------------------------------------------* 28 * ファイルハンドル 29 * - <w0[0:7]>固定値, <w0[8]>有効フラグ, <w0[9:31],w1[0:31]>インクリメント可能 30 *---------------------------------------------------------------------------*/ 31 class Handle 32 { 33 protected: 34 HandleValue m_Data; 35 36 static const bit32 FIXED_VALUE_MASK = 0x0FF; 37 static const bit32 VALID_FLAG_MASK = 0x100; 38 static const bit32 INCREMENT_VALUE = 0x200; 39 40 public: Handle()41 Handle() 42 { 43 m_Data.lo = 0; 44 m_Data.hi = 0; 45 } 46 Handle(bit8 fixedValue)47 Handle(bit8 fixedValue) 48 { 49 m_Data.lo = fixedValue + INCREMENT_VALUE; 50 m_Data.hi = 0; 51 } 52 Handle(const HandleValue & value)53 Handle(const HandleValue& value) 54 { 55 m_Data.lo = value.lo; 56 m_Data.hi = value.hi; 57 } 58 Initialize(bit8 fixedValue)59 void Initialize(bit8 fixedValue) 60 { 61 NN_TASSERT_(!IsInitialized()); 62 m_Data.lo = fixedValue + INCREMENT_VALUE; 63 } 64 Finalize()65 void Finalize() 66 { 67 m_Data.lo = 0; 68 m_Data.hi = 0; 69 } 70 Validate()71 void Validate() 72 { 73 NN_TASSERT_(IsInitialized()); 74 m_Data.lo |= VALID_FLAG_MASK; 75 } 76 Invalidate()77 void Invalidate() 78 { 79 NN_TASSERT_(IsInitialized()); 80 m_Data.lo &= ~VALID_FLAG_MASK; 81 Increment(); 82 } 83 GetFixedValue()84 bit8 GetFixedValue() const { return static_cast<bit8>(m_Data.lo & FIXED_VALUE_MASK); } IsInitialized()85 bool IsInitialized() const { return (m_Data.lo != 0) || (m_Data.hi != 0); } IsValid()86 bool IsValid() const { return (m_Data.lo & VALID_FLAG_MASK) != 0; } 87 HandleValue()88 operator HandleValue() const { return m_Data; } 89 operator const HandleValue&() const { return m_Data; } 90 operator bool() const { return IsValid(); } 91 92 bool operator!() const { return !IsValid(); } 93 bool operator==(const HandleValue& rhs) const { return (m_Data.lo == rhs.lo) && (m_Data.hi == rhs.hi); } 94 bool operator!=(const HandleValue& rhs) const { return (m_Data.lo != rhs.lo) || (m_Data.hi != rhs.hi); } 95 96 protected: Increment()97 void Increment() 98 { 99 m_Data.lo += INCREMENT_VALUE; 100 if (((m_Data.lo & ~FIXED_VALUE_MASK) == 0) && (++m_Data.hi == 0)) 101 { 102 m_Data.lo += INCREMENT_VALUE; 103 } 104 } 105 }; 106 107 /*---------------------------------------------------------------------------* 108 * ハンドルテーブルエントリ 109 *---------------------------------------------------------------------------*/ 110 template<class T> 111 class HandleTableEntry 112 { 113 public: HandleTableEntry()114 HandleTableEntry() {} HandleTableEntry(bit8 fixedValue)115 HandleTableEntry(bit8 fixedValue) { Initialize(fixedValue); } ~HandleTableEntry()116 ~HandleTableEntry() {} 117 118 // 初期化 Initialize(bit8 fixedValue)119 void Initialize(bit8 fixedValue) 120 { 121 NN_TASSERT_(!IsInitialized()); 122 m_Handle.Initialize(fixedValue); 123 } 124 125 // このエントリに紐付けるオブジェクトを登録 Register(const T & object)126 const HandleValue& Register(const T& object) 127 { 128 NN_TASSERT_(!m_Handle.IsValid()); 129 m_Object = object; 130 m_Handle.Validate(); 131 return m_Handle; 132 } 133 134 // 登録を解除(ハンドルを無効にする) Unregister()135 void Unregister() 136 { 137 NN_TASSERT_(m_Handle.IsValid()); 138 m_Handle.Invalidate(); 139 } 140 GetHandle()141 const HandleValue& GetHandle() const { return m_Handle; } GetObject()142 const T& GetObject() const { return m_Object; } IsInitialized()143 bool IsInitialized() const { return m_Handle.IsInitialized(); } IsValid()144 bool IsValid() const { return m_Handle.IsValid(); } HasHandle(HandleValue value)145 bool HasHandle(HandleValue value) const { return IsValid() && (m_Handle == value); } 146 147 private: 148 Handle m_Handle; 149 T m_Object; 150 }; 151 152 /*---------------------------------------------------------------------------* 153 * ハンドルテーブル 154 *---------------------------------------------------------------------------*/ 155 template<class T, size_t TNumEntry> 156 class HandleTable 157 { 158 typedef HandleTableEntry<T> TEntry; 159 160 public: HandleTable()161 HandleTable() {} HandleTable(nn::WithInitialize)162 HandleTable(nn::WithInitialize) { Initialize(); } ~HandleTable()163 ~HandleTable() {} 164 165 // 初期化 166 // - ハンドルの固有値としてインデックスを渡す Initialize()167 void Initialize() 168 { 169 for(s32 i = 0; i < TNumEntry; ++i) 170 { 171 m_Entry[i].Initialize(i); 172 } 173 } 174 175 // オブジェクトの登録 Register(const T & object)176 const HandleValue& Register(const T& object) 177 { 178 TEntry* pEntry = FindFreeEntry(); 179 NN_TASSERT_(pEntry); 180 return pEntry->Register(object); 181 } 182 183 // オブジェクトを削除 Unregister(const HandleValue & value)184 void Unregister(const HandleValue& value) 185 { 186 TEntry* pEntry = const_cast<TEntry*>(FindEntryFromHandle(value)); 187 NN_TASSERT_(pEntry); 188 pEntry->Unregister(); 189 } 190 191 // 指定したハンドルに紐付いているオブジェクトを返す GetObject(const HandleValue & value)192 const T& GetObject(const HandleValue& value) const 193 { 194 const TEntry* pEntry = FindEntryFromHandle(value); 195 NN_TASSERT_(pEntry); 196 return pEntry->GetObject(); 197 } 198 TryGetObject(T * pObject,const HandleValue & value)199 bool TryGetObject(T* pObject, const HandleValue& value) const 200 { 201 const TEntry* pEntry = FindEntryFromHandle(value); 202 if(pEntry) 203 { 204 *pObject = pEntry->GetObject(); 205 return true; 206 } 207 return false; 208 } 209 210 private: 211 TEntry m_Entry[TNumEntry]; 212 213 // 未使用のエントリを探す FindFreeEntry()214 TEntry* FindFreeEntry() 215 { 216 for(s32 i = 0; i < TNumEntry; ++i) 217 { 218 if(!m_Entry[i].IsValid()) 219 { 220 return m_Entry + i; 221 } 222 } 223 return 0; 224 } 225 226 // 指定したハンドルが登録されているエントリを探す FindEntryFromHandle(const HandleValue & value)227 const TEntry* FindEntryFromHandle(const HandleValue& value) const 228 { 229 // 固定値の部分にインデックスを入れているので利用する 230 Handle handle(value); 231 s32 index = handle.GetFixedValue(); 232 233 if(index < TNumEntry) 234 { 235 return m_Entry[index].HasHandle(value) ? (m_Entry + index) : 0; 236 } 237 return 0; 238 } 239 }; 240 241 }} 242 243 #endif // #ifndef NN_FSLOW_FSLOW_HANDLETABLE_H_ 244