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 // Anchors and returns a pointer to D memory, so that it will not 45 // be moved or collected. For use with releaseMem. 46 void* anchorMem(void* ptr) { 47 GC.addRoot(ptr); 48 GC.setAttr(ptr, GC.BlkAttr.NO_MOVE); 49 return ptr; 50 } 51 52 // Passed to sqlite3_xxx_blob64/sqlite3_xxx_text64 to unanchor memory. 53 extern (C) void releaseMem(void* ptr) { 54 GC.setAttr(ptr, GC.BlkAttr.NO_MOVE); 55 GC.removeRoot(ptr); 56 } 57 58 // Adapted from https://p0nce.github.io/d-idioms/#GC-proof-resource-class 59 void ensureNotInGC(T)(string info = null) nothrow { 60 import core.exception : InvalidMemoryOperationError; 61 62 try { 63 import core.memory : GC; 64 65 cast(void) GC.malloc(1); 66 return; 67 } catch (InvalidMemoryOperationError e) { 68 import core.stdc.stdio : fprintf, stderr; 69 import core.stdc.stdlib : exit; 70 71 fprintf(stderr, "Error: clean-up of %s incorrectly depends on destructors called by the GC.\n", 72 T.stringof.ptr); 73 if (info) 74 fprintf(stderr, "Info: %s\n", info.ptr); 75 assert(false); 76 } 77 }