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