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 moduleae.sys.memory;
15 16 importcore.exception;
17 importcore.memory;
18 importcore.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 boolgcRan()
23 {
24 staticboolinitialized = false;
25 staticbooldestroyed = false;
26 27 staticclassBeacon28 {
29 ~this() @nogc30 {
31 destroyed = true;
32 }
33 }
34 35 if (!initialized)
36 {
37 destroyed = false;
38 newBeacon();
39 initialized = true;
40 }
41 42 boolresult = destroyed;
43 if (destroyed)
44 {
45 destroyed = false;
46 newBeacon();
47 }
48 49 returnresult;
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 boolonStack(const(void)* p)
55 {
56 autop0 = thread_stackTop();
57 autop1 = thread_stackBottom();
58 returnp0 <= p && p <= p1;
59 }
60 61 debug(ae_unittest) unittest62 {
63 /* .......... */intl; autopl = &l;
64 static/* ... */ints; autops = &s;
65 static__gsharedintg; autopg = &g;
66 /* ................. */autoph = newint;
67 assert( pl.onStack());
68 assert(!ps.onStack());
69 assert(!pg.onStack());
70 assert(!ph.onStack());
71 }
72 73 privatevoidcallExtend()
74 {
75 // Call GC.extend with dummy data.76 // It will normally exit silently if given a null pointer,77 // but not before the reentrance check.78 GC.extend(null, 0, 0, null);
79 }
80 81 /// Asserts that we are not inside a GC collection cycle,82 /// by performing a no-op GC operation.83 /// If we are, an `InvalidMemoryOperationError` is raised by the runtime.84 voidassertNotInCollect() @nogc85 {
86 (cast(voidfunction() @nogc)&callExtend)();
87 }
88 89 /// Checks if we are inside a GC collection cycle.90 /// This is currently done in a dumb and expensive way, so use sparingly.91 boolinCollect() @nogc92 {
93 try94 assertNotInCollect();
95 catch (InvalidMemoryOperationError)
96 returntrue;
97 returnfalse;
98 }
99 100 debug(ae_unittest) unittest101 {
102 assert(!inCollect());
103 104 classC105 {
106 staticbooltested;
107 108 ~this() @nogc109 {
110 assert(inCollect());
111 tested = true;
112 }
113 }
114 115 foreach (n; 0..128)
116 newC;
117 GC.collect();
118 assert(C.tested);
119 }