1 /** 2 * Memory and GC stuff. 3 * 4 * License: 5 * This Source Code Form is subject to the terms of 6 * the Mozilla Public License, v. 2.0. If a copy of 7 * the MPL was not distributed with this file, You 8 * can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * Authors: 11 * Vladimir Panteleev <ae@cy.md> 12 */ 13 14 module ae.sys.memory; 15 16 import core.exception; 17 import core.memory; 18 import core.thread; 19 20 /// Did the GC run since this function's last call on this thread? 21 /// Not 100% reliable (due to false pointers). 22 bool gcRan() 23 { 24 static bool initialized = false; 25 static bool destroyed = false; 26 27 static class Beacon 28 { 29 ~this() @nogc 30 { 31 destroyed = true; 32 } 33 } 34 35 if (!initialized) 36 { 37 destroyed = false; 38 new Beacon(); 39 initialized = true; 40 } 41 42 bool result = destroyed; 43 if (destroyed) 44 { 45 destroyed = false; 46 new Beacon(); 47 } 48 49 return result; 50 } 51 52 /// Is the given pointer located on the stack of the current thread? 53 /// Useful to assert on before taking the address of e.g. a struct member. 54 bool onStack(const(void)* p) 55 { 56 auto p0 = thread_stackTop(); 57 auto p1 = thread_stackBottom(); 58 return p0 <= p && p <= p1; 59 } 60 61 unittest 62 { 63 /* .......... */ int l; auto pl = &l; 64 static /* ... */ int s; auto ps = &s; 65 static __gshared int g; auto pg = &g; 66 /* ................. */ auto ph = new int; 67 assert( pl.onStack()); 68 assert(!ps.onStack()); 69 assert(!pg.onStack()); 70 assert(!ph.onStack()); 71 } 72 73 /// Checks if we are inside a GC collection cycle. 74 /// This is currently done in a dumb and expensive way, so use sparingly. 75 bool inCollect() @nogc 76 { 77 // Call GC.extend with dummy data. 78 // It will normally exit silently if given a null pointer, 79 // but not before the reentrance check. 80 try 81 (cast(void function(void*, size_t, size_t, const TypeInfo) @nogc)&GC.extend)(null, 0, 0, null); 82 catch (InvalidMemoryOperationError) 83 return true; 84 return false; 85 } 86 87 unittest 88 { 89 assert(!inCollect()); 90 91 class C 92 { 93 static bool tested; 94 95 ~this() @nogc 96 { 97 assert(inCollect()); 98 tested = true; 99 } 100 } 101 102 foreach (n; 0..128) 103 new C; 104 GC.collect(); 105 assert(C.tested); 106 }