1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     fslow_HandleTable.h
4 
5   Copyright 2010 Nintendo. All rights reserved.
6   These coded instructions, statements, and computer programs contain
7   proprietary information of Nintendo of America Inc. and/or Nintendo
8   Company Ltd., and are protected by Federal copyright law. They may
9   not be disclosed to third parties or copied or duplicated in any form,
10   in whole or in part, without the prior written consent of Nintendo.
11   $Rev: 20673 $
12  *---------------------------------------------------------------------------
13 
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  * File handle
29  *    - <w0[0:7]>fixed value, <w0[8]> enable flag, <w0[9:31],w1[0:31]> incrementable
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  * Handle table entry
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     // Initialization
Initialize(bit8 fixedValue)119     void Initialize(bit8 fixedValue)
120     {
121         NN_TASSERT_(!IsInitialized());
122         m_Handle.Initialize(fixedValue);
123     }
124 
125     // Register an object that is tied to this entry
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 (invalidate the handle)
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  * Handle table
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     // Initialization
166     //   - Pass index as unique handle value
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 object
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     // Delete object
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     // Return the object that is tied to the specified handle
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     // Search for unused entry
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     // Search for entries that were registered to the specified handle
FindEntryFromHandle(const HandleValue & value)227     const TEntry* FindEntryFromHandle(const HandleValue& value) const
228     {
229         // Index is inserted into the fixed portion, so use it
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