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 version (checkErrno) pragma(mangle, "getErrno") int fakePureGetErrno(); 16 version (checkErrno) pragma(mangle, "setErrno") int fakePureSetErrno(int); 17 pragma(mangle, "malloc") void* fakePureMalloc(size_t); 18 pragma(mangle, "calloc") void* fakePureCalloc(size_t nmemb, size_t size); 19 pragma(mangle, "realloc") void* fakePureRealloc(void* ptr, size_t size); 20 pragma(mangle, "free") void fakePureFree(void* ptr); 21 } 22 23 // qualified C memory allocations 24 extern(C) pure nothrow @nogc { 25 /* See_Also: 26 * https://forum.dlang.org/post/mailman.1130.1521239659.3374.digitalmars-d@puremagic.com 27 * for an explanation of why `pureMalloc` and `pureCalloc` both can 28 * be @trusted. */ 29 void* malloc(size_t size) @trusted; 30 void* calloc(size_t nmemb, size_t size) @trusted; 31 void* realloc(void* ptr, size_t size) @system; 32 void* alloca(size_t length) @safe; 33 void free(void* ptr) @system; 34 void gc_addRange(const scope void* p, size_t sz, const TypeInfo ti = null); 35 void gc_removeRange(const scope void* p ); 36 } 37 38 /** 39 * Pure variants of C's memory allocation functions `malloc`, `calloc`, and 40 * `realloc` and deallocation function `free`. 41 * 42 * Purity is achieved by saving and restoring the value of `errno`, thus 43 * having as if it were never changed. 44 * 45 * See_Also: 46 * $(LINK2 https://dlang.org/spec/function.html#pure-functions, D's rules for purity), 47 * which allow for memory allocation under specific circumstances. 48 */ 49 private void* pureMalloc(size_t size) @trusted pure @nogc nothrow { 50 version (checkErrno) const errno = fakePureGetErrno(); 51 void* ret = fakePureMalloc(size); 52 version (checkErrno) if (!ret || errno != 0) { 53 cast(void)fakePureSetErrno(errno); 54 } 55 return ret; 56 } 57 /// ditto 58 private void* pureCalloc(size_t nmemb, size_t size) @trusted pure @nogc nothrow { 59 version (checkErrno) const errno = fakePureGetErrno(); 60 void* ret = fakePureCalloc(nmemb, size); 61 version (checkErrno) if (!ret || errno != 0) { 62 cast(void)fakePureSetErrno(errno); 63 } 64 return ret; 65 } 66 /// ditto 67 private void* pureRealloc(void* ptr, size_t size) @system pure @nogc nothrow { 68 version (checkErrno) const errno = fakePureGetErrno(); 69 void* ret = fakePureRealloc(ptr, size); 70 version (checkErrno) if (!ret || errno != 0) { 71 cast(void)fakePureSetErrno(errno); 72 } 73 return ret; 74 } 75 /// ditto 76 void pureFree(void* ptr) @system pure @nogc nothrow { 77 version (checkErrno) const errno = fakePureGetErrno(); 78 fakePureFree(ptr); 79 version (checkErrno) cast(void)fakePureSetErrno(errno); 80 }