1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2019-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 #pragma once
10 
11 #include "types.h"
12 #include "Alloc.h"
13 #include <limits.h>
14 
15 #ifdef ISTDLIB_MT
16 #include "Threading.h"
17 #endif
18 
19 #if defined(MSVC)
20     #define STD_API_CALL __stdcall
21 #else
22     #define STD_API_CALL
23 #endif
24 
25 #define NO_VTABLE __declspec(novtable)
26 
27 namespace iSTD
28 {
29 
30 /*****************************************************************************\
31 
32 Class:
33     CObject
34 
35 Description:
36     Base class for all objects
37 
38 \*****************************************************************************/
39 template<class CAllocatorType>
40 class NO_VTABLE CObject
41 {
42 public:
43 
44     long    Acquire( void );
45     long    Release( void );
46 
47     long    GetRefCount( void ) const;
48 
49     static long STD_API_CALL   SafeAcquire(CObject* ptr);
50     static long STD_API_CALL   SafeRelease(CObject* ptr);
51 
52     void*   operator new( size_t size );
53     void*   operator new[]( size_t size );
54     void*   operator new( size_t size, void* placement);
55     void    operator delete(void* ptr);
56     void    operator delete[]( void* ptr );
57     void    operator delete(void* ptr, void* placement);
58 
59 protected:
60 
61     CObject( void );
62     virtual ~CObject(void);
63 
64 #ifdef ISTDLIB_MT
65     volatile long   m_RefCount;
66 #else
67     long    m_RefCount;
68 #endif
69 };
70 
71 /*****************************************************************************\
72 
73 Function:
74     CObject constructor
75 
76 Description:
77     Initializes internal data
78 
79 Input:
80     default
81 
82 Output:
83     none
84 
85 \*****************************************************************************/
86 template<class CAllocatorType>
CObject(void)87 inline CObject<CAllocatorType>::CObject( void )
88 {
89 #ifdef ISTDLIB_MT
90     ASSERT( IsAligned( (void*)&m_RefCount, sizeof(DWORD) ) );
91 #endif
92     m_RefCount = 0;
93 }
94 
95 /*****************************************************************************\
96 
97 Function:
98     CObject destructor
99 
100 Description:
101     Deletes internal data
102 
103 Input:
104     default
105 
106 Output:
107     none
108 
109 \*****************************************************************************/
110 template<class CAllocatorType>
~CObject(void)111 inline CObject<CAllocatorType>::~CObject(void)
112 {
113     ASSERT( m_RefCount == 0 );
114 }
115 
116 /*****************************************************************************\
117 
118 Function:
119     CObject::Acquire
120 
121 Description:
122     Increments and returns the current reference count
123 
124 Input:
125     none
126 
127 Output:
128     long - reference count
129 
130 \*****************************************************************************/
131 template<class CAllocatorType>
Acquire(void)132 inline long CObject<CAllocatorType>::Acquire( void )
133 {
134     ASSERT( m_RefCount >= 0 );
135     ASSERT( m_RefCount < LONG_MAX );
136 
137 #if defined(ISTDLIB_MT) && defined(__GNUC__)
138     __sync_fetch_and_add(&m_RefCount, 1);
139 #elif defined(ISTDLIB_MT)
140     ::InterlockedIncrement(&m_RefCount);
141 #else
142     ++m_RefCount;
143 #endif
144 
145     return m_RefCount;
146 }
147 
148 /*****************************************************************************\
149 
150 Function:
151     CObject::Release
152 
153 Description:
154     Decrements the current reference count.  Deletes the object when the
155     reference count reaches zero.  Returns the current reference count.
156 
157 Input:
158     none
159 
160 Output:
161     long - reference count
162 
163 \*****************************************************************************/
164 template<class CAllocatorType>
Release(void)165 inline long CObject<CAllocatorType>::Release( void )
166 {
167     ASSERT( m_RefCount > 0 );
168 
169 #if defined(ISTDLIB_MT) && defined(__GNUC__)
170     __sync_sub_and_fetch(&m_RefCount, 1);
171 #elif defined(ISTDLIB_MT)
172     ::InterlockedDecrement(&m_RefCount);
173 #else
174     --m_RefCount;
175 #endif
176 
177     if( m_RefCount == 0 )
178     {
179         delete this;
180         return 0;
181     }
182     else
183     {
184         return m_RefCount;
185     }
186 }
187 
188 /*****************************************************************************\
189 
190 Function:
191     CObject::GetRefCount
192 
193 Description:
194     Returns the current reference count.
195 
196 Input:
197     none
198 
199 Output:
200     long - reference count
201 
202 \*****************************************************************************/
203 template<class CAllocatorType>
GetRefCount(void)204 inline long CObject<CAllocatorType>::GetRefCount( void ) const
205 {
206     return m_RefCount;
207 }
208 
209 /*****************************************************************************\
210 
211 Function:
212     CObject::SafeAcquire
213 
214 Description:
215     Static function that calls the object's acquire function if the object
216     exists
217 
218 Input:
219     CObject* ptr - pointer to object to acquire
220 
221 Output:
222     long - reference count
223 
224 \*****************************************************************************/
225 template<class CAllocatorType>
SafeAcquire(CObject * ptr)226 inline long CObject<CAllocatorType>::SafeAcquire( CObject* ptr )
227 {
228     if( ptr )
229     {
230         return ptr->Acquire();
231     }
232     else
233     {
234         return 0;
235     }
236 }
237 
238 /*****************************************************************************\
239 
240 Function:
241     CObject::SafeRelease
242 
243 Description:
244     Static function that calls the object's release function if the object
245     exists
246 
247 Input:
248     CObject* ptr - pointer to object to release
249 
250 Output:
251     long - reference count
252 
253 \*****************************************************************************/
254 template<class CAllocatorType>
SafeRelease(CObject * ptr)255 inline long CObject<CAllocatorType>::SafeRelease( CObject* ptr )
256 {
257     if( ptr )
258     {
259         return ptr->Release();
260     }
261     else
262     {
263         return 0;
264     }
265 }
266 
267 /*****************************************************************************\
268  operator new
269 \*****************************************************************************/
270 template<class CAllocatorType>
new(size_t size)271 inline void* CObject<CAllocatorType>::operator new( size_t size )
272 {
273     ASSERT( size );
274 
275 #ifdef ISTDLIB_MT
276     void* ptr = CAllocatorType::AlignedAllocate( size, sizeof(DWORD) );
277 #else
278     void* ptr = CAllocatorType::Allocate( size );
279 #endif
280 
281     ASSERT( ptr );
282     return ptr;
283 }
284 
285 /*****************************************************************************\
286  operator new[]
287 \*****************************************************************************/
288 template<class CAllocatorType>
289 inline void* CObject<CAllocatorType>::operator new[]( size_t size )
290 {
291     ASSERT( size );
292 
293 #ifdef ISTDLIB_MT
294     void* ptr = CAllocatorType::AlignedAllocate( size, sizeof(DWORD) );
295 #else
296     void* ptr = CAllocatorType::Allocate( size );
297 #endif
298 
299     ASSERT( ptr );
300     return ptr;
301 }
302 
303 /*****************************************************************************\
304  operator new with placement
305 \*****************************************************************************/
306 template<class CAllocatorType>
new(size_t size,void * placement)307 inline void* CObject<CAllocatorType>::operator new( size_t size, void* placement )
308 {
309     ASSERT( size );
310     ASSERT( placement );
311     return placement;
312 }
313 
314 /*****************************************************************************\
315  operator delete
316 \*****************************************************************************/
317 template<class CAllocatorType>
delete(void * ptr)318 inline void CObject<CAllocatorType>::operator delete(void* ptr)
319 {
320     ASSERT( ptr );
321 
322 #ifdef ISTDLIB_MT
323     CAllocatorType::AlignedDeallocate( ptr );
324 #else
325     CAllocatorType::Deallocate( ptr );
326 #endif
327 }
328 
329 /*****************************************************************************\
330  operator delete[]
331 \*****************************************************************************/
332 template<class CAllocatorType>
333 inline void CObject<CAllocatorType>::operator delete[]( void* ptr )
334 {
335     ASSERT( ptr );
336 
337 #ifdef ISTDLIB_MT
338     CAllocatorType::AlignedDeallocate( ptr );
339 #else
340     CAllocatorType::Deallocate( ptr );
341 #endif
342 }
343 
344 /*****************************************************************************\
345  operator delete from placement
346 \*****************************************************************************/
347 template<class CAllocatorType>
delete(void * ptr,void * placement)348 inline void CObject<CAllocatorType>::operator delete( void* ptr, void* placement )
349 {
350     ASSERT( ptr );
351     ASSERT( placement );
352     ASSERT( ptr == placement );
353 }
354 
355 } // iSTD
356