1 module lwdr; 2 3 pragma(LDC_no_moduleinfo); 4 5 import lifetime.delegate_; 6 public import lwdr.tracking; 7 8 /// A static class by which to interface with core features of LWDR. 9 static final class LWDR 10 { 11 /+/// Finalise and deallocate object `obj` 12 static void free(ref Object obj) nothrow @nogc 13 { 14 import lifetime.class_; 15 _d_delclass(&obj); 16 obj = null; 17 }+/ 18 19 static void free(T)(ref T obj) nothrow @nogc @trusted 20 if(is(T == class) || is(T == interface)) 21 { 22 import lifetime.class_; 23 Object o = cast(Object)obj; 24 _d_delclass(&o); 25 obj = null; 26 } 27 28 version(LWDR_DynamicArray) 29 /// Finalise (if possible) and deallocate dynamic array `arr` 30 static void free(TArr : T[], T)(ref TArr arr) nothrow @trusted 31 { 32 import lifetime.array_; 33 _d_delarray_t(cast(void[]*)&arr, cast(TypeInfo_Struct)typeid(TArr)); // cast to TypeInfo_Struct is acceptable 34 arr = null; 35 } 36 37 /// Deallocate `ptr` 38 static void free(TPtr : T*, T)(ref TPtr ptr) nothrow @trusted 39 if(!is(T == struct)) 40 { 41 import lifetime.common; 42 _d_delmemory(cast(void**)&ptr); 43 ptr = null; 44 } 45 46 /// Finalise (if possible) and deallocate struct pointed to by `ptr`. 47 static void free(TPtr : T*, T)(ref TPtr ptr) nothrow @trusted 48 if(is(T == struct)) 49 { 50 import lifetime.common; 51 TypeInfo_Struct s = cast(TypeInfo_Struct)typeid(T); 52 s.dtor(ptr); 53 _d_delmemory(cast(void**)&ptr); 54 ptr = null; 55 } 56 57 version(LWDR_ManualDelegate) 58 { 59 /++ 60 Deallocate the context for a delegate. If the pointer isn't valid, 61 then no action is taken. Hence, it is safe to call this for all types 62 of delegate context types. 63 ++/ 64 static void freeDelegateContext(void* contextPtr) nothrow @trusted 65 { 66 freeDelegate(contextPtr); 67 } 68 } 69 70 /// Start the runtime. Must be called once per process and before any runtime functionality is used! 71 static void startRuntime() @trusted nothrow 72 { 73 version(LWDR_Sync) 74 { 75 import rt.monitor_; 76 __lwdr_monitor_init; 77 } 78 version(LWDR_ModuleCtors) 79 { 80 import rt.moduleinfo; 81 __lwdr_moduleInfo_runModuleCtors(); 82 } 83 version(LWDR_ManualDelegate) 84 { 85 __lwdr_initLifetimeDelegate(); 86 } 87 } 88 89 /// Stop the runtime. Must be called once per process after all D code has exited. 90 static void stopRuntime() @trusted nothrow 91 { 92 version(LWDR_ModuleCtors) 93 { 94 import rt.moduleinfo; 95 __lwdr_moduleInfo_runModuleDtors(); 96 } 97 version(LWDR_ManualDelegate) 98 { 99 __lwdr_deinitLifetimeDelegate(); 100 } 101 version(LWDR_Sync) 102 { 103 import rt.monitor_; 104 __lwdr_monitor_deinit; 105 } 106 } 107 108 version(LWDR_TLS) 109 { 110 /++ Register the current thread with LWDR. 111 + This will perform the necessary TLS allocations for this thread. ++/ 112 static void registerCurrentThread() nothrow @trusted 113 { 114 import rt.tls; 115 initTLSRanges(); 116 import rt.moduleinfo; 117 __lwdr_moduleInfo_runTlsCtors(); 118 } 119 120 /++ Deregister the current thread from LWDR. 121 + If this thread was not registered, it will cause unknown behaviour. 122 + This will deallocate TLS memory for this thread. ++/ 123 static void deregisterCurrentThread() nothrow @trusted 124 { 125 import rt.moduleinfo; 126 __lwdr_moduleInfo_runTlsDtors(); 127 import rt.tls; 128 freeTLSRanges(); 129 } 130 } 131 } 132 133 /// Initialise LWDR. This forwards to `LWDR.startRuntime`. It is intended for external C code. 134 extern(C) void lwdrStartRuntime() @system nothrow 135 { LWDR.startRuntime; } 136 137 /// Terminate LWDR. This forwards to `LWDR.stopRuntime`. It is intended for external C code. 138 extern(C) void lwdrStopRuntime() @system nothrow 139 { LWDR.stopRuntime; } 140 141 /++ 142 + Mixin for the entry point of the application. Calls `startRuntime` and 143 + `registerCurrentThread` and the respective stop functions on `scope(exit)`. 144 + 145 + May be extended to contain more initialization in the future. 146 + 147 + Examples: 148 + --- 149 + extern(C) void myMain() 150 + { 151 + mixin(LWDREntryPointMixin); 152 + } 153 + --- 154 +/ 155 enum LWDREntryPointMixin = q{ 156 LWDR.startRuntime; // runs the shared static constructors 157 scope(exit) LWDR.stopRuntime; // runs the shared static destructors 158 LWDR.registerCurrentThread; 159 scope(exit) LWDR.deregisterCurrentThread; 160 }; 161 162 /++ 163 + Mixin for the entry point of a secondary thread. Calls 164 + `registerCurrentThread` and the respective stop function on `scope(exit)`. 165 + 166 + May be extended to contain more initialization in the future. 167 + 168 + Don't combine this mixin with `LWDREntryPointMixin` as it already registers 169 + the thread. 170 + 171 + Examples: 172 + --- 173 + extern(C) void secondThreadEntryPoint() 174 + { 175 + mixin(LWDRThreadEntryMixin); 176 + } 177 + --- 178 +/ 179 enum LWDRThreadEntryMixin = q{ 180 LWDR.registerCurrentThread; 181 scope(exit) LWDR.deregisterCurrentThread; 182 };