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