1 /** Qualified C memory management, being `pure nothrow @nogc` and, when 2 * possible, `@trusted`. 3 * 4 * See `std.internal.memory` for Phobos's way of doing this. 5 * 6 * TODO: Use pureMalloc and pureFree instead and remove this module. 7 */ 8 module nxt.qcmeman; 9 10 // disabled for now: 11 // version = checkErrno; 12 13 // locally purified for internal use here only 14 extern (C) private pure @system @nogc nothrow 15 { 16 version(checkErrno) pragma(mangle, "getErrno") int fakePureGetErrno(); 17 version(checkErrno) pragma(mangle, "setErrno") int fakePureSetErrno(int); 18 pragma(mangle, "malloc") void* fakePureMalloc(size_t); 19 pragma(mangle, "calloc") void* fakePureCalloc(size_t nmemb, size_t size); 20 pragma(mangle, "realloc") void* fakePureRealloc(void* ptr, size_t size); 21 pragma(mangle, "free") void fakePureFree(void* ptr); 22 } 23 24 // qualified C memory allocations 25 extern(C) pure nothrow @nogc 26 { 27 /* See_Also: 28 * https://forum.dlang.org/post/mailman.1130.1521239659.3374.digitalmars-d@puremagic.com 29 * for an explanation of why `pureMalloc` and `pureCalloc` both can 30 * be @trusted. */ 31 void* malloc(size_t size) @trusted; 32 void* calloc(size_t nmemb, size_t size) @trusted; 33 void* realloc(void* ptr, size_t size) @system; 34 void* alloca(size_t length) @safe; 35 void free(void* ptr) @system; 36 void gc_addRange(const scope void* p, size_t sz, const TypeInfo ti = null); 37 void gc_removeRange(const scope void* p ); 38 } 39 40 /** 41 * Pure variants of C's memory allocation functions `malloc`, `calloc`, and 42 * `realloc` and deallocation function `free`. 43 * 44 * Purity is achieved by saving and restoring the value of `errno`, thus 45 * having as if it were never changed. 46 * 47 * See_Also: 48 * $(LINK2 https://dlang.org/spec/function.html#pure-functions, D's rules for purity), 49 * which allow for memory allocation under specific circumstances. 50 */ 51 private void* pureMalloc(size_t size) @trusted pure @nogc nothrow 52 { 53 version(checkErrno) const errno = fakePureGetErrno(); 54 void* ret = fakePureMalloc(size); 55 version(checkErrno) if (!ret || errno != 0) 56 { 57 cast(void)fakePureSetErrno(errno); 58 } 59 return ret; 60 } 61 /// ditto 62 private void* pureCalloc(size_t nmemb, size_t size) @trusted pure @nogc nothrow 63 { 64 version(checkErrno) const errno = fakePureGetErrno(); 65 void* ret = fakePureCalloc(nmemb, size); 66 version(checkErrno) if (!ret || errno != 0) 67 { 68 cast(void)fakePureSetErrno(errno); 69 } 70 return ret; 71 } 72 /// ditto 73 private void* pureRealloc(void* ptr, size_t size) @system pure @nogc nothrow 74 { 75 version(checkErrno) const errno = fakePureGetErrno(); 76 void* ret = fakePureRealloc(ptr, size); 77 version(checkErrno) if (!ret || errno != 0) 78 { 79 cast(void)fakePureSetErrno(errno); 80 } 81 return ret; 82 } 83 /// ditto 84 void pureFree(void* ptr) @system pure @nogc nothrow 85 { 86 version(checkErrno) const errno = fakePureGetErrno(); 87 fakePureFree(ptr); 88 version(checkErrno) cast(void)fakePureSetErrno(errno); 89 }