yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
f65d756bf
master
1#include "slang-free-list.h" 2 3// #include "list.h" 4 5namespace Slang 6{ 7 8FreeList ::~FreeList () 9{ 10_deallocateBlocks (m_activeBlocks ); 11_deallocateBlocks (m_freeBlocks ); 12} 13 14void FreeList ::_init () 15{ 16m_top = nullptr ; 17m_end = nullptr ; 18 19m_activeBlocks = nullptr ; 20m_freeBlocks = nullptr ; 21 22m_freeElements = nullptr ; 23 24m_elementSize = 0 ; 25m_alignment = 1 ; 26m_blockSize = 0 ; 27m_blockAllocationSize = 0 ; 28} 29 30void FreeList ::_init (size_t elementSize ,size_t alignment ,size_t elemsPerBlock ) 31{ 32alignment = (alignment < sizeof (void * )) ?sizeof (void * ) :alignment ; 33 34// Alignment must be a power of 2 35assert (((alignment - 1 )& alignment )== 0 ); 36 37// The elementSize must at least be at least the same size as the alignment 38elementSize = (elementSize >=alignment ) ?elementSize :alignment ; 39m_blockSize = elementSize * elemsPerBlock ; 40m_elementSize = elementSize ; 41m_alignment = alignment ; 42 43// Calculate the block size need, correcting for alignment 44const size_t alignedBlockSize = (alignment <=DEFAULT_ALIGNMENT ) 45 ?_calcAlignedBlockSize (DEFAULT_ALIGNMENT ) 46 :_calcAlignedBlockSize (alignment ); 47 48// Make the block struct size aligned 49m_blockAllocationSize = m_blockSize + alignedBlockSize ; 50 51m_top = nullptr ; 52m_end = nullptr ; 53 54m_activeBlocks = nullptr ; 55m_freeBlocks = nullptr ;///< Blocks that there are no allocations in 56 57m_freeElements = nullptr ; 58} 59 60void FreeList ::init (size_t elementSize ,size_t alignment ,size_t elemsPerBlock ) 61{ 62_deallocateBlocks (m_activeBlocks ); 63_deallocateBlocks (m_freeBlocks ); 64_init (elementSize ,alignment ,elemsPerBlock ); 65} 66 67void FreeList ::swapWith (ThisType & rhs ) 68{ 69Swap (m_top ,rhs .m_top ); 70Swap (m_end ,rhs .m_end ); 71 72Swap (m_activeBlocks ,rhs .m_activeBlocks ); 73Swap (m_freeBlocks ,rhs .m_freeBlocks ); 74 75Swap (m_freeElements ,rhs .m_freeElements ); 76 77Swap (m_elementSize ,rhs .m_elementSize ); 78Swap (m_alignment ,rhs .m_alignment ); 79Swap (m_blockSize ,rhs .m_blockSize ); 80Swap (m_blockAllocationSize ,rhs .m_blockAllocationSize ); 81} 82 83void FreeList ::_deallocateBlocks (Block * block ) 84{ 85while (block ) 86 { 87Block * next = block -> m_next ; 88 89#ifdef SLANG_FREE_LIST_INIT_MEM 90Memory ::set (block ,0xfd ,m_blockAllocationSize ); 91#endif 92 93 ::free (block );// deallocate(block, m_blockAllocationSize); 94block = next ; 95 } 96} 97 98bool FreeList ::isValidAllocation (const void * dataIn )const 99{ 100uint8_t * data = (uint8_t * )dataIn ; 101 102Block * block = m_activeBlocks ; 103while (block ) 104 { 105uint8_t * start = block -> m_data ; 106uint8_t * end = start + m_blockSize ; 107 108if (data >=start && data < end ) 109 { 110// Check it's aligned correctly 111if ((data - start ) %m_elementSize ) 112 { 113return false; 114 } 115 116// Non allocated data is between top and end 117if (data >=m_top && data < m_end ) 118 { 119return false; 120 } 121 122// It can't be in the free list 123Element * ele = m_freeElements ; 124while (ele ) 125 { 126if (ele == (Element * )data ) 127 { 128return false; 129 } 130 131ele = ele -> m_next ; 132 } 133return true; 134 } 135 136block = block -> m_next ; 137 } 138// It's not in an active block -> it cannot be a valid allocation 139return false; 140} 141 142void * FreeList ::_allocate () 143{ 144Block * block = m_freeBlocks ; 145if (block ) 146 { 147/// Remove from the free blocks 148m_freeBlocks = block -> m_next ; 149 } 150else 151 { 152// block = (Block*)m_allocator->allocate(m_blockAllocationSize); 153block = (Block * )::malloc (m_blockAllocationSize ); 154if (!block ) 155 { 156// Allocation failed... doh 157return nullptr ; 158 } 159// Do the alignment 160 { 161size_t fix = (size_t (block )+ sizeof (Block )+ m_alignment - 1 )& ~(m_alignment - 1 ); 162block -> m_data = (uint8_t * )fix ; 163 } 164 } 165 166// Attach to the active blocks 167block -> m_next = m_activeBlocks ; 168m_activeBlocks = block ; 169 170// Set up top and end 171m_end = block -> m_data + m_blockSize ; 172 173// Return the first element 174uint8_t * element = block -> m_data ; 175m_top = element + m_elementSize ; 176 177SLANG_FREE_LIST_INIT_ALLOCATE (element ) 178 179return element ; 180} 181 182void FreeList ::deallocateAll () 183{ 184Block * block = m_activeBlocks ; 185if (block ) 186 { 187// Find the end block 188while (block -> m_next ) 189 { 190#ifdef SLANG_FREE_LIST_INIT_MEM 191Memory ::set (block -> m_data ,0xfd ,m_blockSize ); 192#endif 193block = block -> m_next ; 194 } 195// Attach to the freeblocks 196block -> m_next = m_freeBlocks ; 197// The list is now all freelists 198m_freeBlocks = m_activeBlocks ; 199// There are no active blocks 200m_activeBlocks = nullptr ; 201 } 202 203m_top = nullptr ; 204m_end = nullptr ; 205} 206 207void FreeList ::reset () 208{ 209_deallocateBlocks (m_activeBlocks ); 210_deallocateBlocks (m_freeBlocks ); 211 212m_top = nullptr ; 213m_end = nullptr ; 214 215m_activeBlocks = nullptr ; 216m_freeBlocks = nullptr ; 217 218m_freeElements = nullptr ; 219} 220 221 222void FreeList ::_initAllocate (void * mem ) 223{ 224 ::memset (mem ,0xcd ,m_elementSize ); 225} 226 227void FreeList ::_initDeallocate (void * mem ) 228{ 229 ::memset (mem ,0xfd ,m_elementSize ); 230} 231 232}// namespace Slang