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 "Object.h" 12 #include "Threading.h" 13 14 namespace iSTD 15 { 16 17 /*****************************************************************************\ 18 19 Class: 20 CLinearAllocator 21 22 Description: 23 Manages a memory buffer via linear allocation 24 25 \*****************************************************************************/ 26 template<class CAllocatorType> 27 class CLinearAllocator : public CObject<CAllocatorType> 28 { 29 public: 30 31 CLinearAllocator( void* pBaseAddress, const DWORD size ); 32 virtual ~CLinearAllocator( void ); 33 34 DWORD GetAvailableSpace( void ) const; 35 DWORD GetUsedSpace( void ) const; 36 37 void* GetSpace( const DWORD size ); 38 void* GetSpaceAligned( const DWORD size, const DWORD alignSize ); 39 40 bool IsEmpty( void ) const; 41 bool IsFull( void ) const; 42 43 void Align( const DWORD alignSize ); 44 45 void PutSpace( const DWORD size ); 46 void PutAllSpace( void ); 47 48 void* ReserveSpace( const DWORD size ); 49 50 virtual void Resize( const DWORD size ); 51 52 protected: 53 54 void* m_pBaseAddress; 55 DWORD m_Size; // Total size of memory 56 DWORD m_SizeUsed; // Size of used memory 57 DWORD m_SizeReserved; // Size of reserved memory 58 59 DECL_DEBUG_MUTEX( m_InstanceNotThreadSafe ) 60 }; 61 62 /*****************************************************************************\ 63 64 Function: 65 CLinearAllocator Constructor 66 67 Description: 68 Initializes internal data 69 70 Input: 71 void* pBaseAddress 72 const DWORD size 73 74 Output: 75 none 76 77 \*****************************************************************************/ 78 template<class CAllocatorType> CLinearAllocator(void * pBaseAddress,const DWORD size)79inline CLinearAllocator<CAllocatorType>::CLinearAllocator( 80 void* pBaseAddress, 81 const DWORD size ) 82 : CObject<CAllocatorType>() 83 { 84 m_pBaseAddress = pBaseAddress; 85 m_Size = size; 86 m_SizeUsed = 0; 87 m_SizeReserved = 0; 88 89 INIT_DEBUG_MUTEX( m_InstanceNotThreadSafe ); 90 } 91 92 /*****************************************************************************\ 93 94 Function: 95 CLinearAllocator Destructor 96 97 Description: 98 Deletes internal data 99 100 Input: 101 none 102 103 Output: 104 none 105 106 \*****************************************************************************/ 107 template<class CAllocatorType> ~CLinearAllocator(void)108inline CLinearAllocator<CAllocatorType>::~CLinearAllocator( void ) 109 { 110 DELETE_DEBUG_MUTEX( m_InstanceNotThreadSafe ); 111 } 112 113 /*****************************************************************************\ 114 115 Function: 116 CLinearAllocator::GetAvailableSpace 117 118 Description: 119 Gets the amount of space available in the buffer 120 121 Input: 122 none 123 124 Output: 125 DWORD - size in bytes 126 127 \*****************************************************************************/ 128 template<class CAllocatorType> GetAvailableSpace(void)129inline DWORD CLinearAllocator<CAllocatorType>::GetAvailableSpace( void ) const 130 { 131 const DWORD size = m_Size - GetUsedSpace(); 132 return size; 133 } 134 135 /*****************************************************************************\ 136 137 Function: 138 CLinearAllocator::GetUsedSpace 139 140 Description: 141 Gets the amount of space used in the buffer 142 143 Input: 144 none 145 146 Output: 147 DWORD - size in bytes 148 149 \*****************************************************************************/ 150 template<class CAllocatorType> GetUsedSpace(void)151inline DWORD CLinearAllocator<CAllocatorType>::GetUsedSpace( void ) const 152 { 153 const DWORD size = m_SizeUsed + m_SizeReserved; 154 return size; 155 } 156 157 /*****************************************************************************\ 158 159 Function: 160 CLinearAllocator::GetSpace 161 162 Description: 163 Gets space from the top of the buffer 164 165 Input: 166 const DWORD size - size in bytes 167 168 Output: 169 void* - linear address of space 170 171 \*****************************************************************************/ 172 template<class CAllocatorType> GetSpace(const DWORD size)173inline void* CLinearAllocator<CAllocatorType>::GetSpace( const DWORD size ) 174 { 175 ACQUIRE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe ); 176 void* pAddress = NULL; 177 178 if( GetAvailableSpace() >= size ) 179 { 180 pAddress = (BYTE*)m_pBaseAddress + m_SizeUsed; 181 m_SizeUsed += size; 182 } 183 184 RELEASE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe ); 185 return pAddress; 186 } 187 188 /*****************************************************************************\ 189 190 Function: 191 CLinearAllocator::GetSpaceAligned 192 193 Description: 194 Gets space from the top of the buffer 195 196 Input: 197 const DWORD size - size in bytes 198 const DWORD alignSize - alignment in bytes 199 200 Output: 201 void* - linear address of space 202 203 \*****************************************************************************/ 204 template<class CAllocatorType> GetSpaceAligned(const DWORD size,const DWORD alignSize)205inline void* CLinearAllocator<CAllocatorType>::GetSpaceAligned( 206 const DWORD size, 207 const DWORD alignSize ) 208 { 209 ACQUIRE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe ); 210 void* pAddress = NULL; 211 212 if( GetAvailableSpace() >= size ) 213 { 214 // Determine the number of bytes required to 215 // align the allocation 216 const DWORD offset = GetAlignmentOffset( 217 (BYTE*)m_pBaseAddress + m_SizeUsed, 218 alignSize ); 219 220 if( offset ) 221 { 222 if( ( GetAvailableSpace() >= offset ) && 223 ( GetAvailableSpace() >= offset + size ) ) 224 { 225 pAddress = (BYTE*)m_pBaseAddress + m_SizeUsed + offset; 226 m_SizeUsed += size + offset; 227 } 228 } 229 else 230 { 231 pAddress = (BYTE*)m_pBaseAddress + m_SizeUsed; 232 m_SizeUsed += size; 233 } 234 } 235 236 RELEASE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe ); 237 return pAddress; 238 } 239 240 /*****************************************************************************\ 241 242 Function: 243 CLinearAllocator::IsEmpty 244 245 Description: 246 Determines if the buffer is empty 247 248 Input: 249 void 250 251 Output: 252 bool 253 254 \*****************************************************************************/ 255 template<class CAllocatorType> IsEmpty(void)256inline bool CLinearAllocator<CAllocatorType>::IsEmpty( void ) const 257 { 258 const bool isEmpty = ( m_SizeUsed == 0 ) && ( m_SizeReserved == 0 ); 259 return isEmpty; 260 } 261 262 /*****************************************************************************\ 263 264 Function: 265 CLinearAllocator::IsFull 266 267 Description: 268 Determines if the buffer is full 269 270 Input: 271 void 272 273 Output: 274 bool 275 276 \*****************************************************************************/ 277 template<class CAllocatorType> IsFull(void)278inline bool CLinearAllocator<CAllocatorType>::IsFull( void ) const 279 { 280 const bool isFull = ( GetAvailableSpace() == 0 ); 281 return isFull; 282 } 283 284 /*****************************************************************************\ 285 286 Function: 287 CLinearAllocator::Align 288 289 Description: 290 Aligns the buffer and pads with zeros 291 292 Input: 293 const DWORD alignSize - alignment in bytes 294 295 Output: 296 void 297 298 \*****************************************************************************/ 299 template<class CAllocatorType> Align(const DWORD alignSize)300inline void CLinearAllocator<CAllocatorType>::Align( const DWORD alignSize ) 301 { 302 ACQUIRE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe ); 303 304 const DWORD offset = GetAlignmentOffset( 305 (BYTE*)m_pBaseAddress + m_SizeUsed, 306 alignSize ); 307 308 if( offset ) 309 { 310 if( m_Size >= m_SizeUsed + offset ) 311 { 312 m_SizeUsed += offset; 313 } 314 } 315 316 RELEASE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe ); 317 } 318 319 /*****************************************************************************\ 320 321 Function: 322 CLinearAllocator::PutSpace 323 324 Description: 325 Puts space back at the top of the buffer 326 327 Input: 328 const DWORD size - size in bytes 329 330 Output: 331 none 332 333 \*****************************************************************************/ 334 template<class CAllocatorType> PutSpace(const DWORD size)335inline void CLinearAllocator<CAllocatorType>::PutSpace( const DWORD size ) 336 { 337 ACQUIRE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe ); 338 339 m_SizeUsed -= size; 340 341 RELEASE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe ); 342 } 343 344 /*****************************************************************************\ 345 346 Function: 347 CLinearAllocator::PutAllSpace 348 349 Description: 350 Puts all space back 351 352 Input: 353 none 354 355 Output: 356 none 357 358 \*****************************************************************************/ 359 template<class CAllocatorType> PutAllSpace(void)360inline void CLinearAllocator<CAllocatorType>::PutAllSpace( void ) 361 { 362 ACQUIRE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe ); 363 364 m_SizeUsed = 0; 365 m_SizeReserved = 0; 366 367 RELEASE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe ); 368 } 369 370 /*****************************************************************************\ 371 372 Function: 373 CLinearAllocator::ReserveSpace 374 375 Description: 376 Reserves space at the bottom of the buffer 377 378 Input: 379 const DWORD size - size in bytes 380 381 Output: 382 void* - linear address of reserved space 383 384 \*****************************************************************************/ 385 template<class CAllocatorType> ReserveSpace(const DWORD size)386inline void* CLinearAllocator<CAllocatorType>::ReserveSpace( const DWORD size ) 387 { 388 ACQUIRE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe ); 389 void* pAddress = NULL; 390 391 if( GetAvailableSpace() >= size ) 392 { 393 pAddress = (BYTE*)m_pBaseAddress + m_Size - 394 ( m_SizeReserved + size ); 395 m_SizeReserved += size; 396 } 397 398 RELEASE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe ); 399 return pAddress; 400 } 401 402 /*****************************************************************************\ 403 404 Function: 405 CLinearAllocator::Resize 406 407 Description: 408 Changes the size of the buffer 409 410 Input: 411 const DWORD size - size in bytes 412 413 Output: 414 none 415 416 \*****************************************************************************/ 417 template<class CAllocatorType> Resize(const DWORD size)418void CLinearAllocator<CAllocatorType>::Resize( const DWORD size ) 419 { 420 ACQUIRE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe ); 421 422 m_Size = size; 423 424 RELEASE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe ); 425 } 426 427 } // iSTD 428