1 /** 2 Internal Implementation Details. 3 4 You should not import this, as it does not expose any 5 API outside outside of the nulib library. 6 7 Copyright: 8 Copyright © 2023-2025, Kitsunebi Games 9 Copyright © 2023-2025, Inochi2D Project 10 11 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 12 Authors: Luna Nielsen 13 */ 14 module nulib.memory.internal; 15 import numem.core.traits; 16 import numem; 17 18 package(nulib.memory): 19 20 /** 21 Container for refcounted memory. 22 */ 23 struct __refcount_t(T) { 24 @nogc: 25 alias SelfType = typeof(this); 26 alias SelfTypeRef = SelfType*; 27 28 SelfTypeRef self; 29 Ref!T ptr; 30 31 size_t strongrefs; 32 size_t weakrefs; 33 34 // Debug utils for unit testing. 35 version(unittest) { 36 void* userdata; 37 void function(void* userdata) onDeleted; 38 } 39 40 ~this() { 41 ptr = null; 42 self = null; 43 44 version(unittest) { 45 if (onDeleted) { 46 onDeleted(userdata); 47 onDeleted = null; 48 } 49 } 50 } 51 52 void retain(bool strong)() @trusted { 53 static if (strong) 54 strongrefs++; 55 else 56 weakrefs++; 57 } 58 59 void release(bool strong)() @trusted { 60 static if (strong) 61 strongrefs--; 62 else 63 weakrefs--; 64 65 if (strongrefs == 0) { 66 if (ptr) 67 nogc_delete(ptr); 68 69 if (weakrefs == 0 && self) 70 nogc_delete(self); 71 } 72 } 73 74 static SelfTypeRef createNew(Ref!T ptr) @trusted { 75 SelfTypeRef selfptr = nogc_new!(SelfType); 76 77 selfptr.self = selfptr; 78 selfptr.ptr = ptr; 79 selfptr.strongrefs = 1; 80 return selfptr; 81 } 82 83 ref Ref!T get() @trusted nothrow { 84 static if (is(Ref!T == T)) 85 return ptr; 86 else 87 return *ptr; 88 } 89 }