1 /// Author: Aziz Köksal 2 /// License: GPL3 3 /// $(Maturity low) 4 module dil.ChunkAllocator; 5 6 import dil.Array; 7 8 /// Custom non-GC allocator for managing a list of chunks. 9 struct ChunkAllocator 10 { 11 Array chunks; /// List of memory chunks, getting larger progressively. 12 13 /// Constructs a ChunkAllocator. 14 this(size_t size) 15 { 16 initialize(size); 17 } 18 19 /// Initializes with one chunk. 20 void initialize(size_t size) 21 { 22 chunks.cap = 10; // Reserve space for 10 chunks. 23 chunks ~= Array(size); 24 } 25 26 /// Returns chunk number n. 27 Array* lastChunk() 28 { 29 auto chunks = chunks.elems!(Array[]); 30 return chunks.ptr + chunks.length - 1; 31 //return &((chunks.elems!(Array[]))[$-1]); 32 } 33 34 /// Adds a new chunk to the list and returns it. 35 Array* newChunk() 36 { 37 auto cap = lastChunk().cap; 38 cap = (cap << 1) - (cap >> 1); // cap *= 1.5; 39 cap += PAGESIZE - cap % PAGESIZE; // Round up to PAGESIZE. 40 chunks ~= Array(cap); 41 return lastChunk(); 42 } 43 44 /// Returns a chunk that can hold another n bytes. 45 Array* getChunk(size_t n) 46 { 47 auto a = lastChunk(); 48 if (n > a.rem) // Do n bytes fit in? 49 a = newChunk(); 50 return a; 51 } 52 53 /// Returns a pointer to an array of size n bytes. 54 void* allocate(size_t n) 55 { 56 auto a = getChunk(n); 57 auto p = a.cur; 58 a.cur += n; 59 return p; 60 } 61 62 /// Frees all the allocated memory. 63 void destroy() 64 { 65 foreach (ref a; chunks.elems!(Array[])) 66 a.destroy(); 67 chunks.destroy(); 68 } 69 }