1 module nxt.pure_mallocator; 2 3 // TOODO Use std.experimental.allocator.building_blocks.mallocator instead of this module 4 5 import std.experimental.allocator.common; 6 7 /** 8 * The C heap allocator purified. 9 * 10 * TODO Remove when https://github.com/dlang/phobos/pull/6411 has been merged 11 * that adds `calloc`. 12 */ 13 struct PureMallocator 14 { 15 const shared pure nothrow @nogc: 16 17 /** 18 * The alignment is a static constant equal to $(D platformAlignment), which 19 * ensures proper alignment for any D data type. 20 */ 21 enum uint alignment = platformAlignment; 22 23 /** 24 * Standard allocator methods per the semantics defined above. The $(D 25 * deallocate) and $(D reallocate) methods are $(D @system) because they may 26 * move memory around, leaving dangling pointers in user code. Somewhat 27 * paradoxically, $(D malloc) is $(D @safe) but that's only useful to safe 28 * programs that can afford to leak memory allocated. 29 */ 30 void[] allocate(size_t bytes) @trusted 31 { 32 version(LDC) pragma(inline, true); 33 if (!bytes) { return null; } 34 void* p = fakePureMalloc(bytes); 35 return p ? p[0 .. bytes] : null; 36 } 37 38 void[] allocateZeroed(size_t bytes) @trusted 39 { 40 version(LDC) pragma(inline, true); 41 if (!bytes) { return null; } 42 void* p = fakePureCalloc(bytes, 1); 43 return p ? p[0 .. bytes] : null; 44 } 45 46 /// ditto 47 bool deallocate(void[] b) @system 48 { 49 pragma(inline, true); 50 fakePureFree(b.ptr); // `free` doesn't need `b.length` 51 // `true` indicates support, 52 // See_Also: https://dlang.org/phobos/std_experimental_allocator.html#.IAllocator.deallocate 53 return true; 54 } 55 56 /// ditto 57 bool reallocate(ref void[] b, size_t s) @system 58 { 59 if (!s) 60 { 61 // fuzzy area in the C standard, see http://goo.gl/ZpWeSE 62 // so just deallocate and nullify the pointer 63 deallocate(b); 64 b = null; 65 return true; 66 } 67 ubyte* p = cast(ubyte*)fakePureRealloc(b.ptr, s); 68 if (!p) { return false; } 69 b = p[0 .. s]; 70 return true; 71 } 72 73 /// Deallocate using a pointer only like what `free` does. 74 bool deallocatePtr(void* b) @system 75 { 76 pragma(inline, true); 77 fakePureFree(b); // `free` doesn't need `b.length` 78 return true; // `true` indicates support, https://dlang.org/phobos/std_experimental_allocator.html#.IAllocator.deallocate 79 } 80 81 /** 82 * Returns the global instance of this allocator type. The C heap allocator is 83 * thread-safe, therefore all of its methods and `it` itself are 84 * $(D x). 85 */ 86 static shared PureMallocator instance; 87 } 88 89 /// 90 @trusted pure nothrow @nogc unittest 91 { 92 auto buf = PureMallocator.instance.allocate(16); 93 assert(&buf[0]); 94 assert(buf.length); 95 96 assert(PureMallocator.instance.deallocate(buf)); 97 98 import std.experimental.allocator : makeArray; 99 PureMallocator.instance.makeArray!int(64, 42); 100 } 101 102 extern (C) private pure @system @nogc nothrow 103 { 104 pragma(mangle, "malloc") void* fakePureMalloc(size_t); 105 pragma(mangle, "calloc") void* fakePureCalloc(size_t nmemb, size_t size); 106 pragma(mangle, "realloc") void* fakePureRealloc(void* ptr, size_t size); 107 pragma(mangle, "free") void fakePureFree(void* ptr); 108 }