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_FREE_LIST_H 2#define SLANG_CORE_FREE_LIST_H 3 4#include "slang-common.h" 5#include "slang.h" 6 7#include <stdlib.h> 8#include <string.h> 9 10namespace Slang 11{ 12 13#if SLANG_DEBUG 14#define SLANG_FREE_LIST_INIT_MEM 15#endif 16 17#ifdef SLANG_FREE_LIST_INIT_MEM 18#define SLANG_FREE_LIST_INIT_ALLOCATE (ptr ) _initAllocate(ptr); 19#define SLANG_FREE_LIST_INIT_DEALLOCATE (ptr ) _initDeallocate(ptr); 20#else 21#define SLANG_FREE_LIST_INIT_ALLOCATE (ptr ) 22#define SLANG_FREE_LIST_INIT_DEALLOCATE (ptr ) 23#endif 24 25/*! \brief A freelist is a simple and fast memory allocator that can allocate and free in any order 26identically sized blocks. 27 28\details A free list is a memory allocation system that performs allocations/deallocations very 29quickly for elements which are all the same size. In a freelist all elements are the same size, and 30elements can be allocated and freed in any order, as long as every deallocation matches every 31allocation. Both allocation and deallocation are O(1), and generally just a few instructions. The 32underlying memory allocator will allocate in large blocks, with multiple elements amortizing a more 33costly large allocation against lots of fast small element allocations. */ 34class FreeList 35{ 36public : 37typedef FreeList ThisType ; 38 39enum 40 { 41DEFAULT_ALIGNMENT = sizeof (void * ) 42 }; 43 44/// Free elements are held in a singly linked list. The minimum size of an element is therefore 45/// a pointer 46struct Element 47 { 48Element * m_next ; 49 }; 50struct Block 51 { 52Block * m_next ;///< The next block 53uint8_t * m_data ;///< The list of the elements each m_elementSize in size 54 }; 55 56/// Allocate a single element 57SLANG_FORCE_INLINE void * allocate (); 58/// Deallocate a block that was previously allocated with allocate 59SLANG_FORCE_INLINE void deallocate (void * data ); 60 61/// Returns true if this is from a valid allocation 62bool isValidAllocation (const void * dataIn )const ; 63 64/// Get the element size 65SLANG_FORCE_INLINE size_t getElementSize ()const {return m_elementSize ; } 66/// Get the total size of each individual block allocation in bytes 67SLANG_FORCE_INLINE size_t getBlockSize ()const {return m_blockSize ; } 68 69/// Deallocates all elements 70void deallocateAll (); 71/// Deallocates all, and frees any backing memory (put in initial state) 72void reset (); 73 74/// Initialize. If called on an already initialized heap, the heap will be deallocated. 75void init (size_t elementSize ,size_t alignment ,size_t elemsPerBlock ); 76 77/// Swap this with rhs 78void swapWith (ThisType & rhs ); 79 80/// Default Ctor 81FreeList () {_init (); } 82/// Ctor 83FreeList (size_t elementSize ,size_t alignment ,size_t elemsPerBlock ) 84 { 85_init (elementSize ,alignment ,elemsPerBlock ); 86 } 87/// Dtor 88 ~FreeList (); 89 90protected : 91/// Initializes assuming freelist is not constructed 92void _init (size_t elementSize ,size_t alignment ,size_t elemsPerBlock ); 93void * _allocate (); 94void _deallocateBlocks (Block * block ); 95/// Initializes setting everything to empty (doesn't free anything if already allocated) 96void _init (); 97 98SLANG_FORCE_INLINE static size_t _calcAlignedBlockSize (size_t align ) 99 { 100return (sizeof (Block )+ align - 1 )& ~(align - 1 ); 101 } 102 103void _initAllocate (void * mem ); 104void _initDeallocate (void * mem ); 105 106uint8_t * m_top ;///< The top position of the current block 107uint8_t * m_end ;///< The end of the current block 108 109Block * m_activeBlocks ;///< The blocks there are potentially allocations from 110Block * m_freeBlocks ;///< Blocks that there are no allocations in 111 112Element * m_freeElements ;///< A singly linked list of elements available 113 114size_t m_elementSize ; 115size_t m_alignment ; 116size_t m_blockSize ; 117size_t m_blockAllocationSize ;///< The actual allocation size. Maybe bigger than m_blockSize if 118///< alignment requires it. 119}; 120 121// -------------------------------------------------------------------------- 122SLANG_FORCE_INLINE void * FreeList ::allocate () 123{ 124// First see if there are any freeElements ready to go 125 { 126Element * element = m_freeElements ; 127if (element ) 128 { 129m_freeElements = element -> m_next ; 130SLANG_FREE_LIST_INIT_ALLOCATE (element ) 131return element ; 132 } 133 } 134if (m_top >=m_end ) 135 { 136return _allocate (); 137 } 138void * data = (void * )m_top ; 139SLANG_FREE_LIST_INIT_ALLOCATE (data ) 140 141m_top += m_elementSize ; 142return data ; 143} 144// -------------------------------------------------------------------------- 145SLANG_FORCE_INLINE void FreeList ::deallocate (void * data ) 146{ 147assert (isValidAllocation (data )); 148 149SLANG_FREE_LIST_INIT_DEALLOCATE (data ) 150 151// Put onto the singly linked free element list 152Element * ele = (Element * )data ; 153ele -> m_next = m_freeElements ; 154m_freeElements = ele ; 155} 156 157}// namespace Slang 158 159#endif // SLANG_FREE_LIST_H