1 /++ 2 $(H1 Thread-safe reference-counted arrays and pointers) 3 4 Mir provides two kinds of ref-counting pointers and two kinds of ref-counted arrays. 5 6 The first kind pointer is `RCPtr`, which consists of a pointer to the context and pointer to the value.`RCPtr` supports structural and object polymorphism. It allows getting members with the same context as the root. 7 The second kind is `SlimRCPtr`, which consist only from a pointer to the value. The context for `SlimRCPtr`is computed using a fixed-length memory shift from the pointer to the value. 8 `SlimRCPtr` can be converted to an `RCPtr` and to an `RCArray` of the one element. 9 10 `RCArray` is an array type without range primitives. It's length can't be reduced after construction.In the other hand, `Slice!(RCI!(T))` is an ndslice with all random-access range primitives.`RCI` is an iterator, which consists of `RCArray` and the pointer to the current element. 11 `RCArray!T` can be converted or moved to `Slice!(RCI!(T))` using `.asSlice` or `.moveToSlice` methods respectively. 12 13 $(RED `RCArray!T` aliases itself to a common D array slice. This feature may cause a segmentation fault in safe code if used without DIP1000.) 14 15 `RCPtr!T` can be constructed from an element index and `RCArray!T` / `Slice!(RCI!(T))`. 16 17 The package publicly imports $(MREF mir,rc,array), $(MREF mir,rc,ptr), and $(MREF mir,rc,slim_ptr). 18 19 See_also: $(MREF mir,ndslice). 20 +/ 21 module mir.rc; 22 23 /// 24 public import mir.rc.array; 25 /// 26 public import mir.rc.ptr; 27 /// 28 public import mir.rc.slim_ptr; 29 30 import mir.ndslice.slice; 31 32 /++ 33 Returns: shared pointer constructed from the slim shared pointer. 34 35 The function has zero computation cost. 36 +/ 37 RCPtr!F toRCPtr(F)(return SlimRCPtr!F contextAndValue) @trusted 38 { 39 typeof(return) ret; 40 ret._value = contextAndValue._value; 41 ret._context = &contextAndValue.context(); 42 contextAndValue._value = null; 43 return ret; 44 } 45 46 /// 47 version(mir_test) 48 @safe pure @nogc nothrow 49 unittest 50 { 51 import core.lifetime: move; 52 struct S 53 { 54 double e; 55 } 56 struct C 57 { 58 int i; 59 S s; 60 } 61 62 auto a = createSlimRC!C(10, S(3)); 63 auto s = a.move.toRCPtr.shareMember!"s"; 64 assert(s._counter == 1); 65 assert(s.e == 3); 66 } 67 68 /++ 69 Returns: shared pointer constructed with the `array`'s context and the value points to `array[index]`. 70 71 The function has zero computation cost. 72 +/ 73 RCPtr!F toRCPtrAt(F)(return RCArray!F array, size_t index) @trusted 74 if (!is(R == class) && !is(R == interface)) 75 in { 76 assert(index < array.length, "toRCPtrAt: index should be less then array.length"); 77 } 78 do { 79 typeof(return) ret; 80 ret._value = array._payload + index; 81 ret._context = &array.context(); 82 array._payload = null; 83 return ret; 84 } 85 86 /// 87 version(mir_test) 88 @safe pure @nogc nothrow 89 unittest 90 { 91 struct S { double e; } 92 93 auto a = RCArray!S(10); 94 a[3].e = 4; 95 96 auto s = a.toRCPtrAt(3); 97 98 assert(s._counter == 2); 99 assert(s.e == 4); 100 } 101 102 /// ditto 103 RCPtr!F toRCPtrAt(F)(return Slice!(RCI!F) array, size_t index) @trusted 104 if (!is(R == class) && !is(R == interface)) 105 in { 106 assert(index < array.length, "toRCPtrAt: index should be less then array.length"); 107 } 108 do { 109 typeof(return) ret; 110 ret._value = array._iterator._iterator + index; 111 ret._context = &array._iterator._array.context(); 112 array._iterator._array._payload = null; 113 return ret; 114 } 115 116 /// 117 version(mir_test) 118 @safe pure @nogc nothrow 119 unittest 120 { 121 struct S { double e; } 122 123 auto a = RCArray!S(10).asSlice[5 .. $]; 124 a[3].e = 4; 125 126 auto s = a.toRCPtrAt(3); 127 128 assert(s._counter == 2); 129 assert(s.e == 4); 130 } 131 132 /++ 133 Returns: RC array length of one constructed from the slim shared pointer. 134 135 The function has zero computation cost. 136 +/ 137 RCArray!F toRCArray(F)(return SlimRCPtr!F context) @trusted 138 { 139 typeof(return) ret; 140 ret._payload = context._value; 141 context._value = null; 142 return ret; 143 } 144 145 /// 146 version(mir_test) 147 @safe pure @nogc nothrow 148 unittest 149 { 150 struct S { double e; } 151 152 auto a = createSlimRC!S(4).toRCArray; 153 assert(a._counter == 1); 154 assert(a.length == 1); 155 assert(a[0].e == 4); 156 }