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 };