1 /* 2 License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 3 Authors: Adam Búš 4 */ 5 module btl.internal.gc; 6 7 8 9 10 version(D_BetterC){ 11 } 12 else{ 13 version(BTL_GC_RANGE_COUNT) 14 public __gshared int _conter_gc_ranges = 0; 15 16 17 version(BTL_GC_RANGE_TRACK) 18 package __gshared const(void)[][] _gc_ranges = null; 19 20 21 shared static ~this(){ 22 version(BTL_GC_RANGE_COUNT){ 23 import std.conv; 24 if(_conter_gc_ranges != 0) 25 assert(0, "BTL_GC_RANGE_COUNT: " ~ _conter_gc_ranges.to!string ~ " != 0"); 26 } 27 28 29 version(BTL_GC_RANGE_TRACK){ 30 foreach(const(void)[] gcr; _gc_ranges) 31 assert(gcr.length == 0); 32 } 33 } 34 } 35 36 //same as GC.addRange but `pure nothrow @trusted @nogc` and with debug testing 37 public void gcAddRange(T)(const T[] data)pure nothrow @trusted @nogc{ 38 gcAddRange(data.ptr, data.length * T.sizeof); 39 } 40 public void gcAddRange(const void* data, const size_t length)pure nothrow @trusted @nogc{ 41 version(D_BetterC){ 42 } 43 else{ 44 import btl.traits.assume; 45 46 assumePure(function void(const void* ptr, const size_t len){ 47 import core.memory: GC; 48 GC.addRange(ptr, len); 49 })(data, length); 50 51 52 assert(data !is null); 53 assert(length > 0); 54 55 assumePureNoGc(function void(const void* data, const size_t length)@trusted{ 56 version(BTL_GC_RANGE_COUNT){ 57 import core.atomic; 58 atomicFetchAdd!(MemoryOrder.raw)(_conter_gc_ranges, 1); 59 } 60 61 62 63 version(BTL_GC_RANGE_TRACK){ 64 foreach(const void[] gcr; _gc_ranges){ 65 if(gcr.length == 0) 66 continue; 67 68 const void* gcr_end = (gcr.ptr + gcr.length); 69 assert(!(data <= gcr.ptr && gcr.ptr < (data + length))); 70 assert(!(data < gcr_end && gcr_end <= (data + length))); 71 assert(!(gcr.ptr <= data && (data + length) <= gcr_end)); 72 } 73 74 foreach(ref const(void)[] gcr; _gc_ranges){ 75 if(gcr.length == 0){ 76 gcr = data[0 .. length]; 77 return; 78 } 79 } 80 81 _gc_ranges ~= data[0 .. length]; 82 83 } 84 85 })(data, length); 86 } 87 } 88 89 //same as GC.removeRange but `pure nothrow @trusted @nogc` and with debug testing 90 public void gcRemoveRange(T)(const T[] data)pure nothrow @trusted @nogc{ 91 gcRemoveRange(data.ptr); 92 } 93 94 public void gcRemoveRange(const void* data)pure nothrow @trusted @nogc{ 95 version(D_BetterC){ 96 } 97 else{ 98 import btl.traits.assume; 99 100 assumePure(function void(const void* ptr){ 101 import core.memory: GC; 102 GC.removeRange(ptr); 103 })(data); 104 105 assert(data !is null); 106 107 assumePure(function void(const void* data)@trusted{ 108 version(BTL_GC_RANGE_COUNT){ 109 import core.atomic; 110 atomicFetchSub!(MemoryOrder.raw)(_conter_gc_ranges, 1); 111 } 112 113 version(BTL_GC_RANGE_TRACK){ 114 foreach(ref const(void)[] gcr; _gc_ranges){ 115 if(gcr.ptr is data){ 116 gcr = null; 117 return; 118 } 119 const void* gcr_end = (gcr.ptr + gcr.length); 120 assert(!(gcr.ptr <= data && data < gcr_end)); 121 } 122 123 assert(0, "BTL_GC_RANGE_TRACK: missing gc range"); 124 } 125 })(data); 126 } 127 }