1 /** Extra traits for `std.experimental.allocator`; 2 */ 3 module nxt.allocator_traits; 4 5 /** Is `true` iff `T` is an allocator, otherwise `false`. 6 * 7 * Only members and `alignment` and `allocate` are required. 8 * 9 * See_Also: https://dlang.org/phobos/std_experimental_allocator_building_blocks.html 10 * See_Also: https://forum.dlang.org/post/uiavxptceyxsjulkxlec@forum.dlang.org 11 * 12 * TODO: Move to Phobos. 13 */ 14 enum isAllocator(T) = (is(typeof(T.allocate(size_t.init)) == void[]) 15 && is(typeof(T.alignment) : size_t)); // currently either uint or size_t. TODO shall we require T.alignment to be known at compile-time? 16 17 version(unittest) 18 { 19 static assert(isAllocator!NullAllocator); 20 static assert(isAllocator!Mallocator); 21 static assert(isAllocator!GCAllocator); 22 static assert(isAllocator!MmapAllocator); 23 static assert(!isAllocator!int); 24 } 25 26 /** State of an allocator or pointer to an allocator. 27 * 28 * State is zero for `Mallocator`, `GCAllocator`, and `MMapAllocator` and 29 * typically non-zero for the other. 30 * 31 * EMSI containers has this state as their first field. 32 * 33 * TODO: Move to Phobos and put beside 34 * std.experimental.allocator.common.stateSize. 35 */ 36 mixin template AllocatorState(Allocator) // TODO: add string fieldName parameter 37 if (isAllocator!Allocator || 38 isAllocator!(typeof(*Allocator.init))) 39 { 40 private import std.experimental.allocator.common : stateSize; 41 static if (stateSize!Allocator == 0) 42 alias allocator = Allocator.instance; 43 else 44 Allocator allocator; 45 } 46 47 version(unittest) 48 { 49 @safe pure nothrow @nogc unittest 50 { 51 mixin AllocatorState!NullAllocator n; 52 mixin AllocatorState!GCAllocator g; 53 mixin AllocatorState!Mallocator m; 54 mixin AllocatorState!MmapAllocator p; 55 mixin AllocatorState!(MmapAllocator*) pi; 56 } 57 } 58 59 version(unittest) 60 { 61 import std.experimental.allocator.building_blocks.null_allocator : NullAllocator; 62 import std.experimental.allocator.mallocator : Mallocator; 63 import std.experimental.allocator.gc_allocator : GCAllocator; 64 import std.experimental.allocator.mmap_allocator : MmapAllocator; 65 }