1 /+ 2 This module is part of d2sqlite3. 3 4 Authors: 5 Nicolas Sicard (biozic) and other contributors at $(LINK https://github.com/biozic/d2sqlite3) 6 7 Copyright: 8 Copyright 2011-18 Nicolas Sicard. 9 10 License: 11 $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 12 +/ 13 module d2sqlite3.internal.memory; 14 15 import std.traits : isFunctionPointer, isDelegate, isCallable; 16 import core.memory : GC; 17 import core.stdc.stdlib : malloc, free; 18 19 package(d2sqlite3): 20 21 struct WrappedDelegate(T) 22 { 23 T dlg; 24 string name; 25 } 26 27 void* delegateWrap(T)(T dlg, string name = null) nothrow 28 if (isFunctionPointer!T || isDelegate!T) 29 { 30 import std.functional : toDelegate; 31 32 if (dlg is null) 33 return null; 34 35 alias D = typeof(toDelegate(dlg)); 36 auto d = cast(WrappedDelegate!D*) malloc(WrappedDelegate!D.sizeof); 37 d.dlg = toDelegate(dlg); 38 d.name = name; 39 return cast(void*) d; 40 } 41 42 WrappedDelegate!T* delegateUnwrap(T)(void* ptr) nothrow 43 if (isCallable!T) 44 { 45 return cast(WrappedDelegate!T*) ptr; 46 } 47 48 // Anchors and returns a pointer to D memory, so that it will not 49 // be moved or collected. For use with releaseMem. 50 inout(void)* anchorMem(inout(void)* ptr) 51 { 52 GC.addRoot(ptr); 53 // Cast to work around https://issues.dlang.org/show_bug.cgi?id=21484 54 GC.setAttr(cast(void*) ptr, GC.BlkAttr.NO_MOVE); 55 return ptr; 56 } 57 58 // Passed to sqlite3_xxx_blob64/sqlite3_xxx_text64 to unanchor memory. 59 extern(C) void releaseMem(const void* ptr) 60 { 61 // Cast to work around https://issues.dlang.org/show_bug.cgi?id=21484 62 GC.setAttr(cast(void*) ptr, GC.BlkAttr.NO_MOVE); 63 GC.removeRoot(ptr); 64 } 65 66 // Adapted from https://p0nce.github.io/d-idioms/#GC-proof-resource-class 67 void ensureNotInGC(T)(string info = null) nothrow 68 { 69 import core.memory : GC; 70 import core.stdc.stdio : fprintf, stderr; 71 import core.stdc.stdlib : exit; 72 73 if (!GC.inFinalizer) 74 return; 75 76 fprintf(stderr, 77 "Error: clean-up of %s incorrectly depends on destructors called by the GC.\n", 78 T.stringof.ptr); 79 if (info) 80 fprintf(stderr, "Info: %s\n", info.ptr); 81 assert(false); 82 }