| module lib; | |
| // test EH | |
| void throwException() | |
| { | |
| throw new Exception(null); | |
| } | |
| Exception collectException(void delegate() dg) | |
| { | |
| try | |
| dg(); | |
| catch (Exception e) | |
| return e; | |
| return null; | |
| } | |
| // test GC | |
| __gshared Object root; | |
| void alloc() { root = new Object(); } | |
| void access() { assert(root.toString() !is null); } // vtbl call will fail if finalized | |
| void free() { root = null; } | |
| Object tls_root; | |
| void tls_alloc() { tls_root = new Object(); } | |
| void tls_access() { assert(tls_root.toString() !is null); } // vtbl call will fail if finalized | |
| void tls_free() { tls_root = null; } | |
| void stack(alias func)() | |
| { | |
| // allocate some extra stack space to not keep references to GC memory on the scanned stack | |
| ubyte[1024] buf = void; | |
| func(); | |
| } | |
| void testGC() | |
| { | |
| import core.memory; | |
| stack!alloc(); | |
| stack!tls_alloc(); | |
| stack!access(); | |
| stack!tls_access(); | |
| GC.collect(); | |
| stack!tls_access(); | |
| stack!access(); | |
| stack!tls_free(); | |
| stack!free(); | |
| } | |
| // test Init | |
| import core.atomic : atomicOp; | |
| shared uint shared_static_ctor, shared_static_dtor, static_ctor, static_dtor; | |
| shared static this() { if (atomicOp!"+="(shared_static_ctor, 1) != 1) assert(0); } | |
| shared static ~this() { if (atomicOp!"+="(shared_static_dtor, 1) != 1) assert(0); } | |
| static this() { atomicOp!"+="(static_ctor, 1); } | |
| static ~this() { atomicOp!"+="(static_dtor, 1); } | |
| extern(C) int runTests() | |
| { | |
| try | |
| runTestsImpl(); | |
| catch (Throwable) | |
| return 0; | |
| return 1; | |
| } | |
| void runTestsImpl() | |
| { | |
| import core.thread; | |
| bool passed; | |
| try | |
| throwException(); | |
| catch (Exception e) | |
| passed = true; | |
| assert(passed); | |
| assert(collectException({throwException();}) !is null); | |
| testGC(); | |
| assert(shared_static_ctor == 1); | |
| assert(static_ctor == 1); | |
| static void run() | |
| { | |
| assert(static_ctor == 2); | |
| assert(shared_static_ctor == 1); | |
| testGC(); | |
| } | |
| auto thr = new Thread(&run); | |
| thr.start(); | |
| thr.join(); | |
| assert(static_dtor == 1); | |
| passed = false; | |
| foreach (m; ModuleInfo) | |
| if (m.name == "lib") passed = true; | |
| assert(passed); | |
| } | |
| // Provide a way to initialize D from C programs that are D agnostic. | |
| import core.runtime : rt_init, rt_term; | |
| extern(C) int lib_init() | |
| { | |
| return rt_init(); | |
| } | |
| extern(C) int lib_term() | |
| { | |
| return rt_term(); | |
| } | |
| shared size_t* _finalizeCounter; | |
| class MyFinalizer | |
| { | |
| ~this() | |
| { | |
| import core.atomic; | |
| atomicOp!"+="(*_finalizeCounter, 1); | |
| } | |
| } | |
| class MyFinalizerBig : MyFinalizer | |
| { | |
| ubyte[4096] _big = void; | |
| } | |
| extern(C) void setFinalizeCounter(shared(size_t)* p) | |
| { | |
| _finalizeCounter = p; | |
| } |