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