[2.2.1] Merge different codes between 2.2 and 3.0
[platform/framework/native/appfw.git] / src / base / inc / FBase_ObjectManagerImpl.h
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Apache License, Version 2.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 /**
18  * @file        FBase_ObjectManagerImpl.h
19  * @brief       This is the header file for the %_ObjectManagerImpl class.
20  *
21  * This file contains the declarations of the %_ObjectManagerImpl class.
22  */
23 #ifndef _FBASE_INTERNAL_OBJECT_MANAGER_IMPL_H_
24 #define _FBASE_INTERNAL_OBJECT_MANAGER_IMPL_H_
25
26 #include <FBaseObject.h>
27 #include <FBaseColLinkedListT.h>
28 #include <FBaseRtMutex.h>
29 #include <FBaseSysLog.h>
30
31 namespace Tizen { namespace Base
32 {
33
34 class _ObjectManagerImpl
35         : Tizen::Base::Object
36 {
37         struct _HandleElement;
38         union _Handle;
39 public:
40         /**
41          * This is the default constructor for this class.
42          *
43          * @since 2.0
44          */
45         _ObjectManagerImpl(void)
46                 : __slotCount(0)
47         {
48                 __slotCapacity = DEFAULT_CAPACITY;
49                 __pSlots = new _HandleElement[__slotCapacity];
50
51                 __pLock = new (std::nothrow) Tizen::Base::Runtime::Mutex();
52                 SysTryLog(NID_BASE, __pLock != null, "Failed to allocate the mutex instance");
53
54                 result r = __pLock->Create();
55                 SysTryLog(NID_BASE, !IsFailed(r), "Failed to create the mutex instance");
56         }
57
58         /**
59          * This is the destructor for this class.
60          *
61          * @since 2.0
62          */
63         virtual ~_ObjectManagerImpl(void)
64         {
65                 delete[] __pSlots;
66                 //delete __pLock;
67         }
68
69         /**
70          * This is the copy constructor for this class.
71          *
72          * @since 2.0
73          */
74         _ObjectManagerImpl(_ObjectManagerImpl& objectManagerImpl)
75         {
76                 __slotCount = objectManagerImpl.__slotCount;
77                 __slotCapacity = objectManagerImpl.__slotCapacity;
78                 __pSlots = new _HandleElement[objectManagerImpl.__slotCapacity];
79
80                 for (unsigned int i = 0; i < objectManagerImpl.__slotCapacity; i++)
81                 {
82                         __pSlots[i] = objectManagerImpl.__pSlots[i];
83                 }
84
85                 __pLock = new (std::nothrow) Tizen::Base::Runtime::Mutex();
86                 SysTryLog(NID_BASE, __pLock != null, "Failed to allocate the mutex instance");
87
88                 result r = __pLock->Create();
89                 SysTryLog(NID_BASE, !IsFailed(r), "Failed to create the mutex instance");
90         }
91
92         /**
93          * This is the assignement operator for this class.
94          *
95          * @since 2.0
96          */
97         _ObjectManagerImpl& operator =(const _ObjectManagerImpl& pObjectManagerImpl)
98         {
99                 //Check for self-assignment
100                 if (this == &pObjectManagerImpl)
101                 {
102                         return *this;
103                 }
104
105                 delete [] __pSlots;
106                 __pSlots = null;
107
108                 __slotCount = pObjectManagerImpl.__slotCount;
109                 __slotCapacity = pObjectManagerImpl.__slotCapacity;
110                 __pSlots = new _HandleElement[pObjectManagerImpl.__slotCapacity];
111
112                 for (unsigned int i = 0; i < pObjectManagerImpl.__slotCapacity; i++)
113                 {
114                         __pSlots[i] = pObjectManagerImpl.__pSlots[i];
115                 }
116
117                 return *this;
118         }
119
120         /**
121          * Registers the specified object to the object manager.
122          *
123          * @since 2.0
124          * @return              The handle of the object
125          * @param[in]   object          An object to register
126          * @exception   E_SUCCESS       The method was successful.
127          * @see Unregister()
128          */
129         int Register(void* pObject)
130         {
131                 result r = __pLock->Acquire();
132                 SysTryLog(NID_BASE, !IsFailed(r), "Failed to acquire mutex");
133
134                 _Handle handle;
135
136                 if (__freeSlots.GetCount() == 0)
137                 {
138                         unsigned int index = __slotCount;
139
140                         __slotCount++;
141                         if (__slotCount == __slotCapacity)
142                         {
143                                 ExpandSlots();
144                         }
145
146                         InitializeHandle(index, handle);
147
148                         __pSlots[index].__id = handle.__id;
149                         __pSlots[index].__pObject = pObject;
150                 }
151                 else
152                 {
153                         unsigned int index = 0;
154
155                         __freeSlots.GetAt(0, index);
156                         __freeSlots.RemoveAt(0);
157
158                         InitializeHandle(index, handle);
159
160                         __pSlots[index].__id = handle.__id;
161                         __pSlots[index].__pObject = pObject;
162                 }
163
164                 r = __pLock->Release();
165                 SysTryLog(NID_BASE, !IsFailed(r), "Failed to release mutex");
166
167                 return handle.__handle;
168         }
169
170         /**
171          * Unregisters the specified handle from the object manager.
172          *
173          * @since 2.0
174          * @return              The object specified by the handle
175          * @param[in]   handle          A handle to release
176          * @exception   E_SUCCESS       The method was successful.
177          * @exception   E_OBJ_NOT_FOUND The specified handle was not found.
178          * @see Register()
179          */
180         void* Unregister(unsigned int handle)
181         {
182                 result r = __pLock->Acquire();
183                 SysTryLog(NID_BASE, !IsFailed(r), "Failed to acquire mutex");
184
185                 void* pObject = null;
186                 const unsigned int index = ((_Handle*)&handle)->__index;
187
188                 if (index >= __slotCount)
189                 {
190                         r = __pLock->Release();
191                         SysTryLog(NID_BASE, !IsFailed(r), "Failed to release mutex");
192
193                         SetLastResult(E_OBJ_NOT_FOUND);
194                         return null;
195                 }
196
197                 _HandleElement& element = __pSlots[index];
198                 if (element.__id != ((_Handle*)&handle)->__id)
199                 {
200                         r = __pLock->Release();
201                         SysTryLog(NID_BASE, !IsFailed(r), "Failed to release mutex");
202
203                         SetLastResult(E_OBJ_NOT_FOUND);
204                         return null;
205                 }
206
207                 pObject = element.__pObject;
208
209                 element.__id = 0;
210                 element.__pObject = null;
211
212                 __freeSlots.Add(index);
213
214                 r = __pLock->Release();
215                 SysTryLog(NID_BASE, !IsFailed(r), "Failed to release mutex");
216
217                 return pObject;
218         }
219
220         /**
221          * Gets an object specified by the handle.
222          *
223          * @since 2.0
224          * @return              The object specified by the handle
225          * @param[in]   handle          A handle to release
226          * @exception   E_SUCCESS       The method was successful.
227          * @exception   E_OBJ_NOT_FOUND The specified handle was not found.
228          */
229         const void* GetObject(unsigned int handle) const
230         {
231                 result r = __pLock->Acquire();
232                 SysTryLog(NID_BASE, !IsFailed(r), "Failed to acquire mutex");
233
234                 const unsigned int index = ((_Handle*)&handle)->__index;
235
236                 if (index >= __slotCount)
237                 {
238                         r = __pLock->Release();
239                         SysTryLog(NID_BASE, !IsFailed(r), "Failed to release mutex");
240
241                         SetLastResult(E_OBJ_NOT_FOUND);
242                         return null;
243                 }
244
245                 const _HandleElement& element = __pSlots[index];
246                 if (element.__id != ((_Handle*)&handle)->__id)
247                 {
248                         r = __pLock->Release();
249                         SysTryLog(NID_BASE, !IsFailed(r), "Failed to release mutex");
250
251                         SetLastResult(E_OBJ_NOT_FOUND);
252                         return null;
253                 }
254
255                 r = __pLock->Release();
256                 SysTryLog(NID_BASE, !IsFailed(r), "Failed to release mutex");
257
258                 return element.__pObject;
259         }
260
261         /**
262          * Gets an object specified by the handle.
263          *
264          * @since 2.0
265          * @return              The object specified by the handle
266          * @param[in]   handle          A handle to release
267          * @exception   E_SUCCESS       The method was successful.
268          * @exception   E_OBJ_NOT_FOUND The specified handle was not found.
269          */
270         void* GetObject(unsigned int handle)
271         {
272                 const void* pObj = (static_cast<const _ObjectManagerImpl*>(this))->GetObject(handle);
273                 return const_cast<void*>(pObj);
274         }
275
276         /**
277          * Gets the number of objects in the object manager.
278          *
279          * @since 2.0
280          * @return              The number of object
281          */
282         int GetObjectCount(void) const
283         {
284                 result r = __pLock->Acquire();
285                 SysTryLog(NID_BASE, !IsFailed(r), "Failed to acquire mutex");
286
287                 int cnt = static_cast <int>(__slotCount - __freeSlots.GetCount());
288
289                 r = __pLock->Release();
290                 SysTryLog(NID_BASE, !IsFailed(r), "Failed to release mutex");
291
292                 return cnt;
293         }
294
295         bool IsValidHandle(unsigned int handle) const
296         {
297                 const void* pObject = GetObject(handle);
298
299                 if (pObject != null)
300                 {
301                         return true;
302                 }
303                 else
304                 {
305                         return false;
306                 }
307         }
308
309 private:
310         void InitializeHandle(unsigned int index, _Handle& handle)
311         {
312                 static unsigned int autoId = 0;
313                 if (++autoId > MAX_ID)
314                 {
315                         autoId = 1;
316                 }
317
318                 handle.__index = index;
319                 handle.__id = autoId;
320         }
321
322         void ExpandSlots(void)
323         {
324                 unsigned int newCapacity = __slotCapacity*2;
325                 _HandleElement* pNewArray = new _HandleElement[newCapacity];
326
327                 for (unsigned int i = 0; i < __slotCapacity; i++)
328                 {
329                         pNewArray[i] = __pSlots[i];
330                 }
331
332                 delete[] __pSlots;
333
334                 __pSlots = pNewArray;
335                 __slotCapacity = newCapacity;
336         }
337
338         void SetElementAt(int index)
339         {
340         }
341
342         _HandleElement GetElementAt(int index)
343         {
344                 _HandleElement element;
345
346                 return element;
347         }
348
349 private:
350         enum
351         {
352                 MAX_BITS_INDEX = 16,
353                 MAX_BITS_ID = 16,
354                 MAX_INDEX = (1 << MAX_BITS_INDEX) - 1,
355                 MAX_ID = (1 << MAX_BITS_ID) - 1,
356         };
357
358         union _Handle
359         {
360                 unsigned int __handle;
361                 struct
362                 {
363                         unsigned __index    : MAX_BITS_INDEX;
364                         unsigned __id   : MAX_BITS_ID;
365                 };
366         };
367
368         struct _HandleElement
369         {
370                 _HandleElement(unsigned int id = 0, void* pObject = null)
371                         : __id(id)
372                         , __pObject(pObject)
373                 {
374                 }
375
376                 _HandleElement(const _HandleElement& element)
377                 {
378                         __id = element.__id;
379                         __pObject = element.__pObject;
380                 }
381
382                 _HandleElement& operator = (const _HandleElement& element)
383                 {
384                         if (this == &element)
385                         {
386                                 return *this;
387                         }
388
389                         __id = element.__id;
390                         __pObject = element.__pObject;
391
392                         return *this;
393                 }
394
395                 unsigned int __id;
396                 void* __pObject;
397         };
398
399         static const int DEFAULT_CAPACITY = 64;
400
401 private:
402         _HandleElement* __pSlots;
403         unsigned int __slotCount;
404         unsigned int __slotCapacity;
405         Tizen::Base::Collection::LinkedListT<unsigned int> __freeSlots;
406         Tizen::Base::Runtime::Mutex* __pLock;
407
408 };
409 }} // Tizen::Base
410 #endif // _FBASE_INTERNAL_OBJECT_MANAGER_IMPL_H_