1 module btl.autoptr.generational_ptr; 2 3 import btl.internal.allocator; 4 import btl.internal.traits; 5 import btl.internal.gc; 6 7 import btl.autoptr.common; 8 9 10 ///TODO: 11 template GenerationalPtr( 12 _Type, 13 _DestructorType = DestructorType!_Type, 14 bool _weakPtr = false 15 )if(isDestructorType!_DestructorType){ 16 17 static if (is(_Type == class) || is(_Type == interface) || is(_Type == struct) || is(_Type == union)) 18 static assert(!__traits(isNested, _Type), 19 "SharedPtr does not support nested types." 20 ); 21 22 static assert(is(DestructorType!void : _DestructorType), 23 _Type.stringof ~ " wrong DestructorType " ~ DestructorType!void.stringof ~ 24 " : " ~ _DestructorType.stringof 25 ); 26 27 void check_dtor()(){ 28 static assert(is(DestructorType!_Type : _DestructorType), 29 "destructor of type '" ~ _Type.stringof ~ 30 "' doesn't support specified finalizer " ~ _DestructorType.stringof 31 ); 32 } 33 34 import std.meta : AliasSeq; 35 import std.range : ElementEncodingType; 36 import std.traits: Unqual, Unconst, CopyTypeQualifiers, CopyConstness, 37 hasIndirections, hasElaborateDestructor, 38 isMutable, isAbstractClass, isDynamicArray, isStaticArray, isCallable, Select, isArray; 39 40 import core.atomic : MemoryOrder; 41 import core.lifetime : forward; 42 43 enum bool referenceElementType = isClassOrInterface!_Type || isDynamicArray!_Type; 44 45 static if(isDynamicArray!_Type) 46 alias ElementDestructorType() = .DestructorType!void; 47 else 48 alias ElementDestructorType() = .DestructorType!_Type; 49 50 51 enum bool _isLockFree = false; 52 53 struct GenerationalPtr{ 54 55 /** 56 Type of element managed by `SharedPtr`. 57 */ 58 public alias ElementType = _Type; 59 60 61 /** 62 Type of destructor (`void function(void*)@attributes`). 63 */ 64 public alias DestructorType = _DestructorType; 65 66 67 /** 68 Type of control block. 69 */ 70 public alias ControlType = ControlBlock!void; 71 72 73 /** 74 `true` if `SharedPtr` is weak ptr. 75 */ 76 public alias isWeak = _weakPtr; 77 78 79 /** 80 Same as `ElementType*` or `ElementType` if is class/interface/slice. 81 */ 82 public alias ElementReferenceType = ElementReferenceTypeImpl!ElementType; 83 84 85 /** 86 Weak pointer 87 88 `SharedPtr.WeakType` is a smart pointer that holds a non-owning ("weak") reference to an object that is managed by `SharedPtr`. 89 It must be converted to `SharedPtr` in order to access the referenced object. 90 91 `SharedPtr.WeakType` models temporary ownership: when an object needs to be accessed only if it exists, and it may be deleted at any time by someone else, 92 `SharedPtr.WeakType` is used to track the object, and it is converted to `SharedPtr` to assume temporary ownership. 93 If the original `SharedPtr` is destroyed at this time, the object's lifetime is extended until the temporary `SharedPtr` is destroyed as well. 94 95 Another use for `SharedPtr.WeakType` is to break reference cycles formed by objects managed by `SharedPtr`. 96 If such cycle is orphaned (i,e. there are no outside shared pointers into the cycle), the `SharedPtr` reference counts cannot reach zero and the memory is leaked. 97 To prevent this, one of the pointers in the cycle can be made weak. 98 */ 99 static if(hasWeakCounter) 100 public alias WeakType = GenerationalPtr!( 101 _Type, 102 _DestructorType, 103 true 104 ); 105 else 106 public alias WeakType = void; 107 108 109 /** 110 Type of non weak ptr. 111 */ 112 public alias OwningType = GenerationalPtr!( 113 _Type, 114 _DestructorType, 115 false 116 ); 117 118 119 120 /** 121 `true` if shared `SharedPtr` has lock free operations `store`, `load`, `exchange`, `compareExchange`, otherwise 'false' 122 */ 123 public alias isLockFree = _isLockFree; 124 125 126 127 private ElementReferenceType _element; 128 129 static if(isWeak) 130 private size_t _generation; 131 132 private void _set_element(ElementReferenceType e)pure nothrow @system @nogc{ 133 static if(isMutable!ElementReferenceType) 134 this._element = e; 135 else 136 (*cast(Unqual!ElementReferenceType*)&this._element) = cast(Unqual!ElementReferenceType)e; 137 } 138 139 private void _const_set_element(ElementReferenceType e)const pure nothrow @system @nogc{ 140 auto self = cast(Unqual!(typeof(this))*)&this; 141 142 static if(isMutable!ElementReferenceType) 143 self._element = e; 144 else 145 (*cast(Unqual!ElementReferenceType*)&self._element) = cast(Unqual!ElementReferenceType)e; 146 } 147 148 private void _release()scope{ 149 if(false){ 150 DestructorType dt; 151 dt(null); 152 } 153 154 import std.traits : hasIndirections; 155 import core.memory : GC; 156 157 if(this._control !is null) 158 this._control.release!isWeak; 159 } 160 161 private void _reset()scope pure nothrow @system @nogc{ 162 this._control = null; 163 this._set_element(null); 164 } 165 166 private void _const_reset()scope const pure nothrow @system @nogc{ 167 this._const_set_counter(null); 168 this._const_set_element(null); 169 } 170 171 package auto _move()@trusted{ 172 auto e = this._element; 173 auto c = this._control; 174 this._const_reset(); 175 176 return typeof(this)(c, e); 177 } 178 } 179 }