1 module yu.memory.scopedref; 2 3 import std.experimental.allocator; 4 import std.traits : isPointer; 5 6 import yu.traits : Pointer; 7 8 struct IScopedRef(Allocator, T) { 9 alias ValueType = Pointer!T; 10 enum isSaticAlloc = (stateSize!Allocator == 0); 11 static if (isSaticAlloc) 12 alias Alloc = typeof(Allocator.instance); 13 else 14 alias Alloc = Allocator; 15 alias Deleter = void function(ref Alloc, ValueType); 16 17 static if (isSaticAlloc) { 18 this(ValueType ptr) { 19 this(ptr, &defaultDeleter); 20 } 21 22 this(ValueType ptr, Deleter deleter) { 23 _d = ptr; 24 resetDeleter(deleter); 25 } 26 } else { 27 this(Alloc alloc, ValueType ptr) { 28 this(alloc, ptr, &defaultDeleter); 29 } 30 31 this(Alloc alloc, ValueType ptr, Deleter deleter) { 32 _alloc = alloc; 33 _d = ptr; 34 resetDeleter(deleter); 35 } 36 37 @property Alloc allocator() nothrow { 38 return _alloc; 39 } 40 } 41 42 ~this() { 43 release(); 44 } 45 46 void swap(typeof(this) other) { 47 static import std.algorithm.mutation; 48 49 std.algorithm.mutation.swap(other._d, this._d); 50 std.algorithm.mutation.swap(other._deleter, this._deleter); 51 static if (!isSaticAlloc) 52 std.algorithm.mutation.swap(other._alloc, this._alloc); 53 } 54 55 @property ValueType data() { 56 return _d; 57 } 58 59 alias data this; 60 61 bool isNull() nothrow { 62 return (_d is null); 63 } 64 65 void resetDeleter(Deleter dele) 66 in { 67 assert(dele, "Deleter Function must be not null"); 68 } 69 body { 70 _deleter = dele; 71 } 72 73 void reset(ValueType v) { 74 release(); 75 _d = v; 76 } 77 78 static if (isSaticAlloc) { 79 void reset(ValueType v, Alloc alloc) { 80 release(); 81 _alloc = alloc; 82 _d = v; 83 } 84 } 85 86 static if (isPointer!ValueType) { 87 ref T opUnary(string op)() if (op == "*") { 88 return *_d; 89 } 90 } 91 92 ValueType take() nothrow { 93 ValueType ret = _d; 94 _d = null; 95 return ret; 96 } 97 98 void release() { 99 if (_d && _deleter) { 100 _deleter(_alloc, _d); 101 } 102 _d = null; 103 _deleter = &defaultDeleter; 104 } 105 106 @disable this(this); 107 private: 108 static void defaultDeleter(ref Alloc alloc, ValueType value) { 109 alloc.dispose(value); 110 } 111 112 ValueType _d; 113 static if (!isSaticAlloc) 114 Alloc _alloc; 115 else 116 alias _alloc = Alloc.instance; 117 Deleter _deleter = &defaultDeleter; 118 }