00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef _AKARRAY_H
00029 #define _AKARRAY_H
00030
00031 #include <AK/Tools/Common/AkObject.h>
00032 #include <AK/Tools/Common/AkAssert.h>
00033 #include <AK/Tools/Common/AkPlatformFuncs.h>
00034
00035 #define AK_DEFINE_ARRAY_POOL( _name_, _poolID_ ) \
00036 struct _name_ \
00037 { \
00038 static AkMemPoolId Get() \
00039 { \
00040 return _poolID_; \
00041 } \
00042 };
00043
00044 AK_DEFINE_ARRAY_POOL( _ArrayPoolDefault, g_DefaultPoolId )
00045 AK_DEFINE_ARRAY_POOL( _ArrayPoolLEngineDefault, g_LEngineDefaultPoolId )
00046
00047 template <class U_POOL>
00048 struct AkArrayAllocatorNoAlign
00049 {
00050 AkForceInline void * Alloc( size_t in_uSize )
00051 {
00052 return AK::MemoryMgr::Malloc( U_POOL::Get(), in_uSize );
00053 }
00054
00055 AkForceInline void Free( void * in_pAddress )
00056 {
00057 AK::MemoryMgr::Free( U_POOL::Get(), in_pAddress );
00058 }
00059
00060 AkForceInline void TransferMem(void *& io_pDest, AkArrayAllocatorNoAlign<U_POOL> in_srcAlloc, void * in_pSrc )
00061 {
00062 io_pDest = in_pSrc;
00063 }
00064 };
00065
00066 template <class U_POOL>
00067 struct AkArrayAllocatorAlignedSimd
00068 {
00069 AkForceInline void * Alloc( size_t in_uSize )
00070 {
00071 return AK::MemoryMgr::Malign( U_POOL::Get(), in_uSize, AK_SIMD_ALIGNMENT );
00072 }
00073
00074 AkForceInline void Free( void * in_pAddress )
00075 {
00076 AK::MemoryMgr::Falign( U_POOL::Get(), in_pAddress );
00077 }
00078
00079 AkForceInline void TransferMem(void *& io_pDest, AkArrayAllocatorAlignedSimd<U_POOL> in_srcAlloc, void * in_pSrc )
00080 {
00081 io_pDest = in_pSrc;
00082 }
00083
00084 };
00085
00086
00087
00088
00089
00090 template< AkUInt32 uBufferSizeBytes, AkUInt8 uAlignmentSize = AK_OS_STRUCT_ALIGN>
00091 struct AkHybridAllocator
00092 {
00093 static const AkUInt32 _uBufferSizeBytes = uBufferSizeBytes;
00094
00095 AkForceInline void * Alloc(size_t in_uSize)
00096 {
00097 if (in_uSize <= uBufferSizeBytes)
00098 return (void *)&m_buffer;
00099 else
00100 return AK::MemoryMgr::Malign(g_DefaultPoolId, in_uSize, uAlignmentSize);
00101 }
00102
00103 AkForceInline void Free(void * in_pAddress)
00104 {
00105 if (&m_buffer != in_pAddress)
00106 AK::MemoryMgr::Falign(g_DefaultPoolId, in_pAddress);
00107 }
00108
00109 AkForceInline void TransferMem(void *& io_pDest, AkHybridAllocator<uBufferSizeBytes, uAlignmentSize>& in_srcAlloc, void * in_pSrc)
00110 {
00111 if (&in_srcAlloc.m_buffer == in_pSrc)
00112 {
00113 AKPLATFORM::AkMemCpy(m_buffer, in_srcAlloc.m_buffer, uBufferSizeBytes);
00114 io_pDest = m_buffer;
00115 }
00116 else
00117 {
00118 io_pDest = in_pSrc;
00119 }
00120 }
00121
00122 AK_ALIGN(char m_buffer[uBufferSizeBytes], uAlignmentSize);
00123 };
00124
00125 template <class T>
00126 struct AkAssignmentMovePolicy
00127 {
00128
00129
00130 static AkForceInline void Move( T& in_Dest, T& in_Src )
00131 {
00132 in_Dest = in_Src;
00133 }
00134 };
00135
00136
00137 template <class T>
00138 struct AkTransferMovePolicy
00139 {
00140 static AkForceInline void Move( T& in_Dest, T& in_Src )
00141 {
00142 in_Dest.Transfer(in_Src);
00143 }
00144 };
00145
00146
00147 typedef AkArrayAllocatorNoAlign<_ArrayPoolDefault> ArrayPoolDefault;
00148 typedef AkArrayAllocatorNoAlign<_ArrayPoolLEngineDefault> ArrayPoolLEngineDefault;
00149 typedef AkArrayAllocatorAlignedSimd<_ArrayPoolLEngineDefault> ArrayPoolLEngineDefaultAlignedSimd;
00150
00151
00152 template <class T, class ARG_T, class TAlloc = ArrayPoolDefault, unsigned long TGrowBy = 1, class TMovePolicy = AkAssignmentMovePolicy<T> > class AkArray : public TAlloc
00153 {
00154 public:
00155
00156 AkArray()
00157 : m_pItems( 0 )
00158 , m_uLength( 0 )
00159 , m_ulReserved( 0 )
00160 {
00161 }
00162
00163
00164 ~AkArray()
00165 {
00166 AKASSERT( m_pItems == 0 );
00167 AKASSERT( m_uLength == 0 );
00168 AKASSERT( m_ulReserved == 0 );
00169 }
00170
00171
00172
00173 #ifndef SWIG
00174
00175 struct Iterator
00176 {
00177 T* pItem;
00178
00179
00180 Iterator& operator++()
00181 {
00182 AKASSERT( pItem );
00183 ++pItem;
00184 return *this;
00185 }
00186
00187
00188 Iterator& operator--()
00189 {
00190 AKASSERT( pItem );
00191 --pItem;
00192 return *this;
00193 }
00194
00195
00196 T& operator*()
00197 {
00198 AKASSERT( pItem );
00199 return *pItem;
00200 }
00201
00202
00203 bool operator ==( const Iterator& in_rOp ) const
00204 {
00205 return ( pItem == in_rOp.pItem );
00206 }
00207
00208
00209 bool operator !=( const Iterator& in_rOp ) const
00210 {
00211 return ( pItem != in_rOp.pItem );
00212 }
00213 };
00214 #endif // #ifndef SWIG
00215
00216
00217 Iterator Begin() const
00218 {
00219 Iterator returnedIt;
00220 returnedIt.pItem = m_pItems;
00221 return returnedIt;
00222 }
00223
00224
00225 Iterator End() const
00226 {
00227 Iterator returnedIt;
00228 returnedIt.pItem = m_pItems + m_uLength;
00229 return returnedIt;
00230 }
00231
00232
00233 Iterator FindEx( ARG_T in_Item ) const
00234 {
00235 Iterator it = Begin();
00236
00237 for ( Iterator itEnd = End(); it != itEnd; ++it )
00238 {
00239 if ( *it == in_Item )
00240 break;
00241 }
00242
00243 return it;
00244 }
00245
00246
00247
00248 Iterator BinarySearch( ARG_T in_Item ) const
00249 {
00250 Iterator itResult = End();
00251 if (m_pItems)
00252 {
00253 T * pTop = m_pItems, * pBottom = m_pItems + m_uLength;
00254
00255 while ( pTop <= pBottom )
00256 {
00257 T* pThis = ( pBottom - pTop ) / 2 + pTop;
00258 if( in_Item < *pThis )
00259 pBottom = pThis - 1;
00260 else if ( in_Item > *pThis )
00261 pTop = pThis + 1;
00262 else
00263 {
00264 itResult.pItem = pThis;
00265 break;
00266 }
00267 }
00268 }
00269
00270 return itResult;
00271 }
00272
00273
00274 Iterator Erase( Iterator& in_rIter )
00275 {
00276 AKASSERT( m_pItems != 0 );
00277
00278
00279
00280 T * pItemLast = m_pItems + m_uLength - 1;
00281
00282 for ( T * pItem = in_rIter.pItem; pItem < pItemLast; pItem++ )
00283 TMovePolicy::Move( pItem[ 0 ], pItem[ 1 ] );
00284
00285
00286
00287 pItemLast->~T();
00288
00289 m_uLength--;
00290
00291 return in_rIter;
00292 }
00293
00294
00295 void Erase( unsigned int in_uIndex )
00296 {
00297 AKASSERT( m_pItems != 0 );
00298
00299
00300
00301 T * pItemLast = m_pItems + m_uLength - 1;
00302
00303 for ( T * pItem = m_pItems+in_uIndex; pItem < pItemLast; pItem++ )
00304 TMovePolicy::Move( pItem[ 0 ], pItem[ 1 ] );
00305
00306
00307
00308 pItemLast->~T();
00309
00310 m_uLength--;
00311 }
00312
00313
00314
00315 Iterator EraseSwap( Iterator& in_rIter )
00316 {
00317 AKASSERT( m_pItems != 0 );
00318
00319 if ( Length( ) > 1 )
00320 {
00321
00322 TMovePolicy::Move( *in_rIter.pItem, Last( ) );
00323 }
00324
00325
00326 AKASSERT( Length( ) > 0 );
00327 Last( ).~T();
00328
00329 m_uLength--;
00330
00331 return in_rIter;
00332 }
00333
00334
00335 AKRESULT Reserve( AkUInt32 in_ulReserve )
00336 {
00337 AKASSERT( m_pItems == 0 && m_uLength == 0 );
00338 AKASSERT( in_ulReserve || TGrowBy );
00339
00340 if ( in_ulReserve )
00341 {
00342 m_pItems = (T *) TAlloc::Alloc( sizeof( T ) * in_ulReserve );
00343 if ( m_pItems == 0 )
00344 return AK_InsufficientMemory;
00345
00346 m_ulReserved = in_ulReserve;
00347 }
00348
00349 return AK_Success;
00350 }
00351
00352 AkUInt32 Reserved() const { return m_ulReserved; }
00353
00354
00355 void Term()
00356 {
00357 if ( m_pItems )
00358 {
00359 RemoveAll();
00360 TAlloc::Free( m_pItems );
00361 m_pItems = 0;
00362 m_ulReserved = 0;
00363 }
00364 }
00365
00366
00367 AkForceInline AkUInt32 Length() const
00368 {
00369 return m_uLength;
00370 }
00371
00372
00373 AkForceInline bool IsEmpty() const
00374 {
00375 return m_uLength == 0;
00376 }
00377
00378
00379 T* Exists(ARG_T in_Item) const
00380 {
00381 Iterator it = FindEx( in_Item );
00382 return ( it != End() ) ? it.pItem : 0;
00383 }
00384
00385
00386
00387 T * AddLast()
00388 {
00389 size_t cItems = Length();
00390
00391 #if defined(_MSC_VER)
00392 #pragma warning( push )
00393 #pragma warning( disable : 4127 )
00394 #endif
00395 if ( ( cItems >= m_ulReserved ) && TGrowBy > 0 )
00396 {
00397 if ( !GrowArray() )
00398 return 0;
00399 }
00400 #if defined(_MSC_VER)
00401 #pragma warning( pop )
00402 #endif
00403
00404
00405 if( cItems < m_ulReserved )
00406 {
00407 T * pEnd = m_pItems + m_uLength++;
00408 AkPlacementNew( pEnd ) T;
00409 return pEnd;
00410 }
00411
00412 return 0;
00413 }
00414
00415
00416 T * AddLast(ARG_T in_rItem)
00417 {
00418 T * pItem = AddLast();
00419 if ( pItem )
00420 *pItem = in_rItem;
00421 return pItem;
00422 }
00423
00424
00425 T& Last()
00426 {
00427 AKASSERT( m_uLength );
00428
00429 return *( m_pItems + m_uLength - 1 );
00430 }
00431
00432
00433 void RemoveLast()
00434 {
00435 AKASSERT( m_uLength );
00436 ( m_pItems + m_uLength - 1 )->~T();
00437 m_uLength--;
00438 }
00439
00440
00441 AKRESULT Remove(ARG_T in_rItem)
00442 {
00443 Iterator it = FindEx( in_rItem );
00444 if ( it != End() )
00445 {
00446 Erase( it );
00447 return AK_Success;
00448 }
00449
00450 return AK_Fail;
00451 }
00452
00453
00454
00455 AKRESULT RemoveSwap(ARG_T in_rItem)
00456 {
00457 Iterator it = FindEx( in_rItem );
00458 if ( it != End() )
00459 {
00460 EraseSwap( it );
00461 return AK_Success;
00462 }
00463
00464 return AK_Fail;
00465 }
00466
00467
00468 void RemoveAll()
00469 {
00470 for ( Iterator it = Begin(), itEnd = End(); it != itEnd; ++it )
00471 (*it).~T();
00472 m_uLength = 0;
00473 }
00474
00475
00476 AkForceInline T& operator[](unsigned int uiIndex) const
00477 {
00478 AKASSERT( m_pItems );
00479 AKASSERT( uiIndex < Length() );
00480 return m_pItems[uiIndex];
00481 }
00482
00483
00484
00485 T * Insert(unsigned int in_uIndex)
00486 {
00487 AKASSERT( in_uIndex <= Length() );
00488
00489 size_t cItems = Length();
00490
00491 #if defined(_MSC_VER)
00492 #pragma warning( push )
00493 #pragma warning( disable : 4127 )
00494 #endif
00495 if ( ( cItems >= m_ulReserved ) && TGrowBy > 0 )
00496 {
00497 if ( !GrowArray() )
00498 return 0;
00499 }
00500 #if defined(_MSC_VER)
00501 #pragma warning( pop )
00502 #endif
00503
00504
00505 if( cItems < m_ulReserved )
00506 {
00507 T * pItemLast = m_pItems + m_uLength++;
00508 AkPlacementNew( pItemLast ) T;
00509
00510
00511
00512 for ( T * pItem = pItemLast; pItem > ( m_pItems + in_uIndex ); --pItem )
00513 TMovePolicy::Move( pItem[ 0 ], pItem[ -1 ] );
00514
00515
00516
00517 ( m_pItems + in_uIndex )->~T();
00518 AkPlacementNew( m_pItems + in_uIndex ) T;
00519
00520 return m_pItems + in_uIndex;
00521 }
00522
00523 return 0;
00524 }
00525
00526
00527 bool GrowArray( AkUInt32 in_uGrowBy = TGrowBy )
00528 {
00529 AKASSERT( in_uGrowBy );
00530
00531 AkUInt32 ulNewReserve = m_ulReserved + in_uGrowBy;
00532 T * pNewItems = (T *) TAlloc::Alloc( sizeof( T ) * ulNewReserve );
00533 if ( !pNewItems )
00534 return false;
00535
00536
00537
00538 size_t cItems = Length();
00539
00540 if ( m_pItems && m_pItems != pNewItems )
00541 {
00542 for ( size_t i = 0; i < cItems; ++i )
00543 {
00544 AkPlacementNew( pNewItems + i ) T;
00545
00546 TMovePolicy::Move( pNewItems[ i ], m_pItems[ i ] );
00547
00548 m_pItems[ i ].~T();
00549 }
00550
00551 TAlloc::Free( m_pItems );
00552 }
00553
00554 m_pItems = pNewItems;
00555 m_ulReserved = ulNewReserve;
00556
00557 return true;
00558 }
00559
00560
00561 bool Resize(AkUInt32 in_uiSize)
00562 {
00563 AkUInt32 cItems = Length();
00564 if (in_uiSize < cItems)
00565 {
00566
00567 for(AkUInt32 i = in_uiSize - 1 ; i < cItems; i++)
00568 {
00569 m_pItems[ i ].~T();
00570 }
00571 m_uLength = in_uiSize;
00572 return true;
00573 }
00574
00575 if ( in_uiSize > m_ulReserved )
00576 {
00577 if ( !GrowArray(in_uiSize - cItems) )
00578 return false;
00579 }
00580
00581
00582 for(size_t i = cItems; i < in_uiSize; i++)
00583 {
00584 AkPlacementNew( m_pItems + i ) T;
00585 }
00586
00587 m_uLength = in_uiSize;
00588 return true;
00589 }
00590
00591 void Transfer(AkArray<T,ARG_T,TAlloc,TGrowBy,TMovePolicy>& in_rSource)
00592 {
00593 Term();
00594
00595 TAlloc::TransferMem( (void*&)m_pItems, in_rSource, (void*)in_rSource.m_pItems );
00596 m_uLength = in_rSource.m_uLength;
00597 m_ulReserved = in_rSource.m_ulReserved;
00598
00599 in_rSource.m_pItems = NULL;
00600 in_rSource.m_uLength = 0;
00601 in_rSource.m_ulReserved = 0;
00602 }
00603
00604 AKRESULT Copy(const AkArray<T, ARG_T, TAlloc, TGrowBy, TMovePolicy>& in_rSource)
00605 {
00606 Term();
00607
00608 if (Resize(in_rSource.Length()))
00609 {
00610 for (AkUInt32 i = 0; i < in_rSource.Length(); ++i)
00611 m_pItems[i] = in_rSource.m_pItems[i];
00612 return AK_Success;
00613 }
00614 return AK_Fail;
00615 }
00616
00617 protected:
00618
00619 T * m_pItems;
00620 AkUInt32 m_uLength;
00621 AkUInt32 m_ulReserved;
00622 };
00623
00624
00625 #endif