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 module nxt.qcmeman; 7 8 // disabled for now: 9 // version = checkErrno; 10 11 // locally purified for internal use here only 12 extern (C) private pure @system @nogc nothrow 13 { 14 version(checkErrno) pragma(mangle, "getErrno") int fakePureGetErrno(); 15 version(checkErrno) pragma(mangle, "setErrno") int fakePureSetErrno(int); 16 pragma(mangle, "malloc") void* fakePureMalloc(size_t); 17 pragma(mangle, "calloc") void* fakePureCalloc(size_t nmemb, size_t size); 18 pragma(mangle, "realloc") void* fakePureRealloc(void* ptr, size_t size); 19 pragma(mangle, "free") void fakePureFree(void* ptr); 20 } 21 22 // qualified C memory allocations 23 extern(C) pure nothrow @nogc 24 { 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(in void* p, size_t sz, const TypeInfo ti = null); 35 void gc_removeRange(in 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 { 51 version(checkErrno) const errno = fakePureGetErrno(); 52 void* ret = fakePureMalloc(size); 53 version(checkErrno) if (!ret || errno != 0) 54 { 55 cast(void)fakePureSetErrno(errno); 56 } 57 return ret; 58 } 59 /// ditto 60 private void* pureCalloc(size_t nmemb, size_t size) @trusted pure @nogc nothrow 61 { 62 version(checkErrno) const errno = fakePureGetErrno(); 63 void* ret = fakePureCalloc(nmemb, size); 64 version(checkErrno) if (!ret || errno != 0) 65 { 66 cast(void)fakePureSetErrno(errno); 67 } 68 return ret; 69 } 70 /// ditto 71 private void* pureRealloc(void* ptr, size_t size) @system pure @nogc nothrow 72 { 73 version(checkErrno) const errno = fakePureGetErrno(); 74 void* ret = fakePureRealloc(ptr, size); 75 version(checkErrno) if (!ret || errno != 0) 76 { 77 cast(void)fakePureSetErrno(errno); 78 } 79 return ret; 80 } 81 /// ditto 82 void pureFree(void* ptr) @system pure @nogc nothrow 83 { 84 version(checkErrno) const errno = fakePureGetErrno(); 85 fakePureFree(ptr); 86 version(checkErrno) cast(void)fakePureSetErrno(errno); 87 }