1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     fslow_HandleTable.h
4 
5   Copyright (C)2009-2012 Nintendo Co., Ltd.  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: 46347 $
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