1import core.thread, core.memory, core.atomic;
2
3// test init
4shared uint gctor, gdtor, tctor, tdtor;
5shared static this() { if (atomicOp!"+="(gctor, 1) != 1) assert(0); }
6shared static ~this() { if (atomicOp!"+="(gdtor, 1) != 1) assert(0); }
7static this() { atomicOp!"+="(tctor, 1); }
8static ~this() { atomicOp!"+="(tdtor, 1); }
9
10// test GC
11__gshared Object root;
12void alloc() { root = new Object(); }
13void access() { assert(root.toString() !is null); } // vtbl call will fail if finalized
14void free() { root = null; }
15
16Object tls_root;
17void tls_alloc() { tls_root = new Object(); }
18void tls_access() { assert(tls_root.toString() !is null); } // vtbl call will fail if finalized
19void tls_free() { tls_root = null; }
20
21void stack(alias func)()
22{
23    // allocate some extra stack space to not keep references to GC memory on the scanned stack
24    ubyte[1024] buf = void;
25    func();
26}
27
28void testGC()
29{
30    import core.memory;
31
32    stack!alloc();
33    stack!tls_alloc();
34    stack!access();
35    stack!tls_access();
36    GC.collect();
37    stack!tls_access();
38    stack!access();
39    stack!tls_free();
40    stack!free();
41}
42
43extern(C) int runTests()
44{
45    try
46    {
47        assert(atomicLoad!(MemoryOrder.acq)(gctor) == 1);
48        assert(atomicLoad!(MemoryOrder.acq)(gdtor) == 0);
49        assert(atomicLoad!(MemoryOrder.acq)(tctor) >= 1);
50        assert(atomicLoad!(MemoryOrder.acq)(tdtor) >= 0);
51        // test some runtime functionality
52        testGC();
53        new Thread(&testGC).start.join;
54    }
55    catch (Throwable)
56    {
57        return false;
58    }
59    return true;
60}
61
62// Provide a way to initialize D from C programs that are D agnostic.
63import core.runtime : rt_init, rt_term;
64
65extern(C) int plugin_init()
66{
67    return rt_init();
68}
69
70extern(C) int plugin_term()
71{
72    return rt_term();
73}
74