11/+ +
2+ $(H1 Thread-safe reference-counted arrays and iterators).
23+/
34module mir.rcarray ;
45
@@ -24,10 +25,8 @@ private template preferCppLinkage(T)
2425 enum preferCppLinkage = true ;
2526 else
2627 enum preferCppLinkage = false ;
27-
2828}
2929
30- // /
3130version (mir_test)
3231unittest
3332{
@@ -42,10 +41,6 @@ unittest
4241 static assert (! preferCppLinkage! (immutable C));
4342}
4443
45- // extern(C++)
46- // enum C {e, b}
47- // pragma(msg, __traits(getLinkage, C));
48-
4944/+ +
5045Thread safe reference counting array.
5146
@@ -54,8 +49,9 @@ Thread safe reference counting array.
5449The implementation never adds roots into the GC.
5550+/
5651struct mir_rcarray (T)
57- if (T.alignof <= 16 )
5852{
53+ import std.traits ;
54+
5955 enum cppSupport = preferCppLinkage! T;
6056
6157 private struct Context
@@ -79,29 +75,6 @@ struct mir_rcarray(T)
7975 return * cast (inout (Context* )* )&_payload;
8076 }
8177
82- // private inout(Context)* _context() inout @trusted pure nothrow @nogc scope
83- // {
84- // return cast(Context*) _contextCode;
85- // }
86-
87- // private void _context(Context * context) @trusted pure nothrow @nogc scope
88- // {
89- // _contextCode = cast(size_t) context;
90- // }
91-
92- // /
93- this (this ) scope @trusted pure nothrow @nogc
94- {
95- import core.atomic : atomicOp;
96- if (_context ! is null ) with (* _context)
97- {
98- if (counter)
99- {
100- counter.atomicOp! " +=" (1 );
101- }
102- }
103- }
104-
10578 private void dec ()() scope
10679 {
10780 import core.atomic : atomicOp;
@@ -111,7 +84,6 @@ struct mir_rcarray(T)
11184 {
11285 if (counter.atomicOp! " -=" (1 ) == 0 )
11386 {
114- import std.traits : Unqual;
11587 import mir.conv: xdestroy;
11688 Unqual! T[] array;
11789 ()@trusted { array = (cast (Unqual! T* )(_context + 1 ))[0 .. length]; }();
@@ -143,20 +115,21 @@ struct mir_rcarray(T)
143115 }
144116 }
145117
146- static if (cppSupport) extern ( C++ )
118+ static if (cppSupport)
147119 {
120+ extern (C++ ):
148121 // /
149122 pragma (inline, false )
150- ~this () scope nothrow @nogc @safe
123+ ~this () nothrow @nogc @safe
151124 {
152125 dec();
153126 }
154127
155- // /
128+ // / Extern constructor
156129 pragma (inline, false )
157- bool initialize (size_t length, uint alignment = T.alignof , bool deallocate = true ) scope @safe nothrow @nogc
130+ bool initialize (size_t length, uint alignment, bool deallocate, bool initialize ) scope @safe nothrow @nogc
158131 {
159- return initializeImpl (length, alignment, deallocate);
132+ return initializeImpl (length, alignment, deallocate, initialize );
160133 }
161134
162135 // /
@@ -169,15 +142,29 @@ struct mir_rcarray(T)
169142 else
170143 {
171144 pragma (inline, false )
172- ~this () scope nothrow @nogc @safe
145+ ~this () nothrow @nogc @safe
173146 {
174147 dec();
175148 }
176149
150+ // / Extern constructor
177151 pragma (inline, false )
178- bool initialize (size_t length, uint alignment = T.alignof , bool deallocate = true ) scope @safe nothrow @nogc
152+ bool initialize (size_t length, uint alignment, bool deallocate, bool initialize ) scope @safe nothrow @nogc
179153 {
180- return initializeImpl (length, alignment, deallocate);
154+ return initializeImpl (length, alignment, deallocate, initialize);
155+ }
156+ }
157+
158+ // /
159+ this (this ) scope @trusted pure nothrow @nogc
160+ {
161+ import core.atomic : atomicOp;
162+ if (_context ! is null ) with (* _context)
163+ {
164+ if (counter)
165+ {
166+ counter.atomicOp! " +=" (1 );
167+ }
181168 }
182169 }
183170
@@ -186,10 +173,11 @@ struct mir_rcarray(T)
186173 length = array length
187174 alignment = alignment, must be power of 2
188175 deallocate = Flag, never deallocates memory if `false`.
176+ initialize = Flag, don't initialize memory with default value if `false`.
189177 +/
190- this (size_t length, uint alignment = T.alignof, bool deallocate = true ) scope @trusted @nogc
178+ this (size_t length, uint alignment = T.alignof, bool deallocate = true , bool initialize = true ) @safe @nogc
191179 {
192- if (! initialize(length, alignment, deallocate))
180+ if (! this . initialize(length, alignment, deallocate, initialize ))
193181 {
194182 version (D_Exceptions)
195183 {
@@ -199,10 +187,67 @@ struct mir_rcarray(T)
199187 {
200188 assert (0 , allocationExcMsg);
201189 }
202- }
190+ }
191+ }
192+
193+ static if (isImplicitlyConvertible! (const T, T))
194+ static if (isImplicitlyConvertible! (const Unqual! T, T))
195+ private alias V = const Unqual! T;
196+ else
197+ private alias V = const T;
198+ else
199+ private alias V = T;
200+
201+ static if (hasIndirections! T)
202+ /+ +
203+ Contructor is defined if `hasIndirections!T == true`.
204+ +/
205+ static typeof (this ) create (V[] values ... ) @safe @nogc
206+ {
207+ auto ret = typeof (this )(values .length, T.alignof, true , false );
208+ static if (! hasElaborateAssign! T)
209+ {
210+ ()@trusted {
211+ import core.stdc.string : memcpy;
212+ memcpy(cast (void * )ret.ptr, cast (const void * )values .ptr, values .length * T.sizeof);
213+ }();
214+ }
215+ else
216+ {
217+ import mir.conv: emplaceRef;
218+ auto lhs = ret[];
219+ foreach (i, ref e; values )
220+ lhs[i].emplaceRef(e);
221+ }
222+ return ret;
223+ }
224+
225+ static if (! hasIndirections! T)
226+ /+ +
227+ Contructor is defined if `hasIndirections!T == false`.
228+ +/
229+ static typeof (this ) create (scope V[] values ... ) @trusted @nogc
230+ {
231+ auto ret = RCArray! T(values .length, T.alignof, true , false );
232+ static if (! hasElaborateAssign! T)
233+ {
234+ ()@trusted {
235+ import core.stdc.string : memcpy;
236+ memcpy(cast (void * )ret.ptr, cast (const void * )values .ptr, values .length * T.sizeof);
237+ }();
238+ }
239+ else
240+ {
241+ import mir.conv: emplaceRef;
242+ auto lhs = ret[];
243+ foreach (i, ref e; values )
244+ lhs[i].emplaceRef(e);
245+ }
246+ import std.algorithm.mutation : move;
247+ return ret;
203248 }
204249
205- private bool initializeImpl ()(size_t length, uint alignment, bool deallocate) scope @trusted nothrow @nogc
250+ private bool initializeImpl ()(size_t length, uint alignment, bool deallocate, bool initialize ) scope @trusted nothrow @nogc
206251 {
207252 if (length == 0 )
208253 {
@@ -238,9 +283,12 @@ struct mir_rcarray(T)
238283
239284 _context.length = length;
240285 _context.counter = deallocate; // 0
241- import mir.conv: uninitializedFillDefault;
242- import std.traits : Unqual;
243- uninitializedFillDefault((cast (Unqual! T* )(_context + 1 ))[0 .. _context.length]);
286+ if (initialize)
287+ {
288+ import mir.conv: uninitializedFillDefault;
289+ import std.traits : Unqual;
290+ uninitializedFillDefault((cast (Unqual! T* )(_context + 1 ))[0 .. _context.length]);
291+ }
244292 return true ;
245293 }
246294
@@ -321,9 +369,35 @@ unittest
321369 assert (a[4 ] == 100 );
322370
323371 import mir.ndslice.slice;
324- auto s = a.toSlice;
372+
373+ auto s = a.asSlice; // as RC random access range (ndslice)
325374 static assert (is (typeof (s) == Slice! (RCI ! double )));
326375 static assert (is (typeof (s) == mir_slice! (mir_rci! double )));
376+
377+ auto r = a[]; // scope array
378+ static assert (is (typeof (r) == double []));
379+
380+ auto fs = r.sliced; // scope fast random access range (ndslice)
381+ static assert (is (typeof (fs) == Slice! (double * )));
382+ }
383+
384+ // /
385+ version (mir_test)
386+ @safe pure @nogc
387+ unittest
388+ {
389+ auto a = RCArray! double .create(1.0 , 2 , 5 , 3 );
390+ assert (a[0 ] == 1 );
391+ assert (a[$ - 1 ] == 3 );
392+
393+ auto s = RCArray! char .create(" hello!" );
394+ assert (s[0 ] == ' h' );
395+ assert (s[$ - 1 ] == ' !' );
396+
397+ alias rcstring = RCArray! (immutable char ).create;
398+ auto r = rcstring(" string" );
399+ assert (r[0 ] == ' s' );
400+ assert (r[$ - 1 ] == ' g' );
327401}
328402
329403/+ +
@@ -334,20 +408,9 @@ struct mir_rci(T)
334408 // /
335409 T* _iterator;
336410
337- // private inout(T)* _iterator() inout @trusted pure nothrow @nogc scope
338- // {
339- // return cast(T*) _iteratorCode;
340- // }
341-
342- // private void _iterator(T * iterator) @trusted pure nothrow @nogc scope
343- // {
344- // _iteratorCode = cast(size_t) iterator;
345- // }
346-
347411 // /
348412 RCArray! T _array;
349413
350-
351414 mir_rci! (const T) lightConst() scope return const @nogc nothrow @trusted @property
352415 { return typeof (return )(_iterator, _array.lightConst); }
353416
@@ -465,3 +528,28 @@ version(mir_test)
465528 b = a;
466529 }
467530}
531+
532+ version (mir_test)
533+ unittest
534+ {
535+ import mir.ndslice.slice: Slice;
536+ static RCArray! int foo () @safe
537+ {
538+ auto ret = RCArray! int (10 );
539+ return ret;
540+ }
541+
542+
543+ static Slice! (RCI ! int ) bat () @safe
544+ {
545+ auto ret = RCArray! int (10 );
546+ return ret.asSlice;
547+ }
548+
549+ static Slice! (RCI ! int ) bar () @safe
550+ {
551+ auto ret = RCArray! int (10 );
552+ auto d = ret.asSlice;
553+ return d;
554+ }
555+ }
0 commit comments