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 T dlg; 23 string name; 24 } 25 26 void* delegateWrap(T)(T dlg, string name = null) nothrow 27 if (isFunctionPointer!T || isDelegate!T) { 28 import std.functional : toDelegate; 29 30 if (dlg is null) 31 return null; 32 33 alias D = typeof(toDelegate(dlg)); 34 auto d = cast(WrappedDelegate!D*) malloc(WrappedDelegate!D.sizeof); 35 d.dlg = toDelegate(dlg); 36 d.name = name; 37 return cast(void*) d; 38 } 39 40 WrappedDelegate!T* delegateUnwrap(T)(void* ptr) nothrow if (isCallable!T) { 41 return cast(WrappedDelegate!T*) ptr; 42 } 43 44 extern (C) void ptrFree(void* ptr) nothrow { 45 free(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 void* anchorMem(void* ptr) { 51 GC.addRoot(ptr); 52 GC.setAttr(ptr, GC.BlkAttr.NO_MOVE); 53 return ptr; 54 } 55 56 // Passed to sqlite3_xxx_blob64/sqlite3_xxx_text64 to unanchor memory. 57 extern (C) void releaseMem(void* ptr) { 58 GC.setAttr(ptr, GC.BlkAttr.NO_MOVE); 59 GC.removeRoot(ptr); 60 } 61 62 // Adapted from https://p0nce.github.io/d-idioms/#GC-proof-resource-class 63 void ensureNotInGC(T)(string info = null) nothrow { 64 import core.exception : InvalidMemoryOperationError; 65 66 try { 67 import core.memory : GC; 68 69 cast(void) GC.malloc(1); 70 return; 71 } catch (InvalidMemoryOperationError e) { 72 import core.stdc.stdio : fprintf, stderr; 73 import core.stdc.stdlib : exit; 74 75 fprintf(stderr, "Error: clean-up of %s incorrectly depends on destructors called by the GC.\n", 76 T.stringof.ptr); 77 if (info) 78 fprintf(stderr, "Info: %s\n", info.ptr); 79 assert(false); 80 } 81 }