1 /** 2 Memory provider allocators to be used in templated composition 3 within other, designated allocators. 4 5 Copyright: © 2012-2013 RejectedSoftware e.K. 6 © 2014-2015 Etienne Cimon 7 License: Subject to the terms of the MIT license. 8 Authors: Sönke Ludwig, Etienne Cimon 9 */ 10 module memutils.memory; 11 12 import memutils.allocators; 13 import memutils.helpers; 14 import std.algorithm : min; 15 import std.c.stdlib; 16 17 final class GCAllocator : Allocator { 18 import core.memory : GC; 19 void[] alloc(size_t sz) 20 { 21 auto mem = GC.malloc(sz+Allocator.alignment); 22 auto alignedmem = adjustPointerAlignment(mem); 23 assert(alignedmem - mem <= Allocator.alignment); 24 auto ret = alignedmem[0 .. sz]; 25 ensureValidMemory(ret); 26 return ret; 27 } 28 29 void[] realloc(void[] mem, size_t new_size) 30 { 31 size_t csz = min(mem.length, new_size); 32 33 auto p = extractUnalignedPointer(mem.ptr); 34 size_t misalign = mem.ptr - p; 35 assert(misalign <= Allocator.alignment); 36 37 void[] ret; 38 auto extended = GC.extend(p, new_size - mem.length, new_size - mem.length); 39 if (extended) { 40 assert(extended >= new_size+Allocator.alignment); 41 ret = p[misalign .. new_size+misalign]; 42 } else { 43 ret = alloc(new_size); 44 ret[0 .. csz] = mem[0 .. csz]; 45 } 46 ensureValidMemory(ret); 47 return ret; 48 } 49 50 /// calls to free are optional if stability is favored over speed 51 void free(void[] mem) 52 { 53 GC.free(extractUnalignedPointer(mem.ptr)); 54 } 55 } 56 57 final class MallocAllocator : Allocator { 58 void[] alloc(size_t sz) 59 { 60 static err = new immutable OutOfMemoryError; 61 auto ptr = .malloc(sz + Allocator.alignment); 62 if (ptr is null) throw err; 63 return adjustPointerAlignment(ptr)[0 .. sz]; 64 } 65 66 void[] realloc(void[] mem, size_t new_size) 67 { 68 size_t csz = min(mem.length, new_size); 69 auto p = extractUnalignedPointer(mem.ptr); 70 size_t oldmisalign = mem.ptr - p; 71 72 auto pn = cast(ubyte*).realloc(p, new_size+Allocator.alignment); 73 if (p == pn) return pn[oldmisalign .. new_size+oldmisalign]; 74 75 auto pna = cast(ubyte*)adjustPointerAlignment(pn); 76 auto newmisalign = pna - pn; 77 78 // account for changed alignment after realloc (move memory back to aligned position) 79 if (oldmisalign != newmisalign) { 80 if (newmisalign > oldmisalign) { 81 foreach_reverse (i; 0 .. csz) 82 pn[i + newmisalign] = pn[i + oldmisalign]; 83 } else { 84 foreach (i; 0 .. csz) 85 pn[i + newmisalign] = pn[i + oldmisalign]; 86 } 87 } 88 89 return pna[0 .. new_size]; 90 } 91 92 void free(void[] mem) 93 { 94 .free(extractUnalignedPointer(mem.ptr)); 95 } 96 }