The OpenD Programming Language

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 }