1 module tardy.allocators; 2 3 4 import tardy.from; 5 6 7 template SBOAllocator(size_t N) { 8 import std.experimental.allocator.building_blocks.fallback_allocator: FallbackAllocator; 9 import std.experimental.allocator.mallocator: Mallocator; 10 11 alias SBOAllocator = FallbackAllocator!( 12 InSitu!N, 13 Mallocator, 14 ); 15 } 16 17 18 struct InSitu(size_t N) { 19 20 import std.experimental.allocator: platformAlignment; 21 22 enum alignment = platformAlignment; 23 static assert(N >= alignment); 24 25 union { 26 private ubyte[N] _buffer; 27 private double _forAlignmentOnly_; 28 } 29 30 @disable this(this); 31 32 void[] allocate(size_t n) return scope { 33 return _buffer[0 .. n]; 34 } 35 36 bool deallocate(scope void[] buf) const { 37 import std.typecons: Ternary; 38 import std.traits: functionAttributes, FA = FunctionAttribute; 39 40 static impl() { 41 throw new Exception("Not my buffer"); 42 } 43 44 if(owns(buf) == Ternary.no) { 45 static if(functionAttributes!impl & FA.nogc) 46 impl; 47 else 48 assert(false, "Not my buffer"); 49 } 50 51 return true; 52 } 53 54 auto owns(scope void[] buf) const { 55 import std.typecons: Ternary; 56 return buf.ptr is _buffer.ptr 57 ? Ternary.yes 58 : Ternary.no; 59 } 60 } 61 62 63 struct GC { 64 65 import std.experimental.allocator.gc_allocator: GCAllocator; 66 67 enum alignment = GCAllocator.alignment; 68 69 static GC instance; 70 71 void[] allocate(size_t n) @safe return scope pure nothrow { 72 return GCAllocator.instance.allocate(n); 73 } 74 75 bool deallocate(scope void[]) @safe scope pure nothrow @nogc const { 76 // By never deallocating, all operations using this allocator can 77 // be @trusted 78 return true; 79 } 80 81 }