yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
f65d756bf
master
1#ifndef SLANG_CORE_CHUNKED_LIST_H 2#define SLANG_CORE_CHUNKED_LIST_H 3 4#include "slang-allocator.h" 5#include "slang-array-view.h" 6#include "slang-math.h" 7#include "slang.h" 8 9namespace Slang 10{ 11// Items stored in a ChunkedList are guaranteed to have fixed address. 12template < typename T ,uint32_t defaultChunkSize = 16 ,typename TAllocator = StandardAllocator > 13class ChunkedList 14{ 15private : 16TAllocator allocator ; 17 18struct Chunk 19 { 20uint32_t size = 0 ; 21uint32_t capacity = defaultChunkSize ; 22Chunk * next = nullptr; 23T * begin () {return reinterpret_cast < T *> (this + 1 ); } 24T * end () {return begin ()+ size ; } 25 }; 26 27struct FirstChunk :public Chunk 28 { 29T elements [defaultChunkSize ]; 30 }; 31 32Chunk * allocateChunk (uint32_t size ) 33 { 34 autoresultChunk = ( Chunk * )allocator. allocate ( sizeof (Chunk) + size * sizeof ( T )); 35resultChunk -> capacity = size; 36resultChunk -> size = 0 ; 37resultChunk -> next = nullptr ; 38auto firstItem = resultChunk -> begin (); 39if (!std::is_trivially_constructible_v < T > ) 40{ 41for ( uint32_t i = 0 ; i < size; i ++ ) 42new (firstItem + i) T (); 43} 44return resultChunk; 45} 46void freeChunk ( Chunk * chunk) 47{ 48if (!std::is_trivially_destructible_v < T > ) 49{ 50for ( uint32_t i = 0 ; i < chunk -> capacity ; i ++ ) 51chunk -> begin ()[i].~ T (); 52} 53allocator. deallocate (chunk); 54} 55 56public: 57typedef ChunkedList < T , defaultChunkSize, TAllocator > ThisType; 58ChunkedList () 59: m_lastChunk ( & m_firstChunk), m_count ( 0 ) 60{ 61} 62template < typename... Args > 63ChunkedList (const T & val, Args... args) 64{ 65_init (val, args...); 66} 67ChunkedList( const ThisType & list) 68: m_lastChunk ( & m_firstChunk ), m_count ( 0 ) 69{ 70this -> operator = (list); 71} 72ChunkedList (ThisType && list) 73: m_lastChunk ( & m_firstChunk), m_count ( 0 ) 74{ 75this -> operator = (static_cast < ThisType &&> (list)); 76} 77~ ChunkedList () { _deallocateBuffer (); } 78template < int _otherShortListSize, typename TOtherAllocator > 79ThisType & operator = ( const ChunkedList < T , _otherShortListSize, TOtherAllocator >& list) 80{ 81clearAndDeallocate (); 82addRange (list); 83return * this; 84} 85 86ThisType & operator = ( const ThisType & other) 87{ 88clearAndDeallocate (); 89addRange (other); 90return * this; 91} 92 93ThisType & operator = (ThisType && list) 94{ 95// Could just do a swap here, and memory would be freed on rhs dtor 96_deallocateBuffer (); 97m_count = list. m_count ; 98m_firstChunk = _Move (list. m_firstChunk ); 99m_lastChunk = list. m_lastChunk ; 100list. m_count = 0 ; 101list. m_firstChunk . next = nullptr ; 102list. m_lastChunk = & list. m_firstChunk ; 103list. m_firstChunk . size = 0 ; 104return * this; 105} 106 107struct Iterator 108{ 109Chunk * chunk = nullptr; 110Index index = -1 ; 111Iterator & operator ++ () 112{ 113++ index ; 114if ( index == chunk -> size) 115{ 116index = 0 ; 117chunk = chunk -> next ; 118} 119return * this; 120} 121Iterator operator ++ ( int ) 122{ 123Iterator rs = * this; 124operator ++ (); 125return rs; 126} 127T * operator -> () 128{ 129SLANG_ASSERT( chunk ); 130return chunk -> begin() + index ; 131} 132T & operator * () 133{ 134SLANG_ASSERT( chunk ); 135return chunk -> begin()[ index ]; 136} 137bool operator == ( Iterator other ) { return chunk == other . chunk && index == other . index ; } 138bool operator != ( Iterator other ) { return index != other . index || chunk != other . chunk ; } 139}; 140 141Iterator begin () 142{ 143Iterator rs ; 144rs . chunk = & m_firstChunk ; 145rs . index = 0 ; 146return rs ; 147} 148Iterator end () 149{ 150Iterator rs ; 151rs . chunk = nullptr ; 152rs . index = 0 ; 153return rs ; 154} 155 156Chunk * _maybeReserveForAdd( uint32_t chunkSize ) 157{ 158if ( m_lastChunk -> capacity - m_lastChunk -> size < chunkSize ) 159{ 160auto chunk = allocateChunk( Math ::Max( defaultChunkSize , chunkSize )); 161m_lastChunk -> next = chunk ; 162m_lastChunk = chunk ; 163return chunk ; 164} 165return m_lastChunk ; 166} 167 168T * add( T && obj ) 169{ 170auto chunk = _maybeReserveForAdd ( 1 ); 171auto result = chunk -> begin () + chunk -> size ; 172chunk -> begin ()[chunk -> size ] = static_cast < T &&> (obj); 173chunk -> size ++ ; 174m_count ++ ; 175return result; 176} 177 178T * add (const T & obj) 179{ 180auto chunk = _maybeReserveForAdd ( 1 ); 181auto result = chunk -> begin () + chunk -> size ; 182chunk -> begin ()[chunk -> size ] = obj; 183chunk -> size ++ ; 184m_count ++ ; 185return result; 186} 187 188Index getCount () const { return m_count; } 189 190T * addRange (const T * vals, Index n) 191{ 192Chunk * chunk = _maybeReserveForAdd (( uint32_t )n); 193auto result = chunk -> begin () + chunk -> size ; 194for ( Index i = 0 ; i < n; i ++ ) 195{ 196chunk -> begin ()[chunk -> size + i] = vals[i]; 197} 198chunk -> size += ( uint32_t )n; 199m_count += n; 200return result; 201} 202 203T * addRange (ArrayView < T > list) { return addRange (list. m_buffer , list. m_count ); } 204 205T * reserveRange (uint32_t size) 206{ 207Chunk * chunk = _maybeReserveForAdd (( uint32_t )size); 208auto result = chunk -> begin () + chunk -> size ; 209chunk -> size += size; 210m_count += size; 211return result; 212} 213 214template < typename TContainer > 215T * addRange (const TContainer & list) 216{ 217Chunk * chunk = _maybeReserveForAdd (( uint32_t )list. getCount ()); 218auto result = chunk -> begin () + chunk -> size ; 219for (auto & obj : list) 220{ 221chunk -> begin ()[chunk -> size ] = obj; 222chunk -> size ++ ; 223m_count ++ ; 224} 225return result; 226} 227 228void clearAndDeallocate () 229{ 230_deallocateBuffer (); 231m_count = 0 ; 232for (auto & item : m_firstChunk. elements ) 233item = T (); 234} 235 236private: 237Index m_count = 0 ; ///< The amount of elements 238FirstChunk m_firstChunk; 239Chunk * m_lastChunk = & m_firstChunk; 240 241void _deallocateBuffer () 242{ 243auto chunk = m_firstChunk. next ; 244while (chunk) 245{ 246auto nextChunk = chunk -> next ; 247freeChunk (chunk); 248chunk = nextChunk; 249} 250m_firstChunk. next = 0 ; 251m_firstChunk. size = 0 ; 252m_lastChunk = & m_firstChunk; 253} 254static inline T * _allocate (Index count) 255{ 256return AllocateMethod < T , TAllocator > :: allocateArray (count); 257} 258static inline void _free( T * ptr, Index count) 259{ 260return AllocateMethod < T , TAllocator > :: deallocateArray (ptr, count); 261} 262 263template < typename... Args > 264void _init( const T & val, Args... args) 265{ 266add (val); 267_init( args ...); 268} 269 270void _init () {} 271}; 272} // namespace Slang 273 274#endif