1 module lifetime.delegate_;
2 
3 pragma(LDC_no_moduleinfo);
4 
5 import lwdr.internal.arr;
6 import lwdr.tracking;
7 
8 version(LWDR_ManualDelegate):
9 
10 version(LWDR_ManualDelegate_16Dels)
11 	private enum numDelegatesTrack = 16; // Can track 16 delegate contexts, maximum
12 version(LWDR_ManualDelegate_32Dels)
13 	private enum numDelegatesTrack = 32; // Can track 32 delegate contexts, maximum
14 version(LWDR_ManualDelegate_64Dels)
15 	private enum numDelegatesTrack = 64; // Can track 64 delegate contexts, maximum
16 else
17 	private enum numDelegatesTrack = 8; // Can track 8 delegate contexts, maximum
18 
19 /// Keeps track of delegate context allocations
20 private __gshared LLArray delegateContextAllocations;
21 
22 /++
23 Allocate `sz` amount of bytes for a delegate context.
24 The ptr to the context will be stored in an internal array
25 for book keeping.
26 ++/
27 extern(C) void* _d_allocmemory(size_t sz) @trusted
28 {
29 	void* ptr = lwdrInternal_alloc(sz);
30 	bool added = delegateContextAllocations.add(ptr);
31 	assert(added); // Panic if out of room to store the context
32 	return ptr;
33 }
34 
35 /++
36 Deallocate the context for a delegate. If the pointer isn't valid,
37 then no action is taken. Hence, it is safe to call this for all types
38 of delegate context types.
39 ++/
40 void freeDelegate(void* contextPtr) @trusted nothrow
41 {
42 	if(delegateContextAllocations.invalidate(contextPtr))
43 	{
44 		import lifetime.common;
45 		_d_delmemory(&contextPtr);
46 	}
47 }
48 
49 /// INTERNAL LWDR USE! Allocates the book keeping system for delegate context allocations.
50 void __lwdr_initLifetimeDelegate() @system nothrow
51 {
52 	delegateContextAllocations = LLArray(numDelegatesTrack);
53 }
54 
55 /// INTERNAL LWDR USE! Deallocates the book keeping system and any residual contexts.
56 void __lwdr_deinitLifetimeDelegate() @system nothrow
57 {
58 	foreach(ref size_t ptr; delegateContextAllocations.unsafeRange)
59 	{
60 		// If the runtime is exiting, assume safe to unload any memory not already freed
61 		import lifetime.common;
62 		_d_delmemory(cast(void**)&ptr);
63 	}
64 	delegateContextAllocations.dealloc;
65 }