1 /**
2     Implementation of non aliasable reference counted pointer `RcPtr` (similar to c++ `std::shared_ptr` without aliasing).
3 
4     License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
5     Authors:   Adam Búš
6 */
7 module btl.autoptr.rc_ptr;
8 
9 import btl.traits.common;
10 
11 import btl.internal.allocator;
12 import btl.internal.traits;
13 import btl.internal.gc;
14 
15 import btl.autoptr.common;
16 
17 
18 /**
19     Check if type `T` is `RcPtr`.
20 */
21 public template isRcPtr(T){
22     import std.traits : isInstanceOf;
23 
24     enum bool isRcPtr = isInstanceOf!(RcPtr, T);
25 }
26 
27 ///
28 unittest{
29     static assert(!isRcPtr!long);
30     static assert(!isRcPtr!(void*));
31 
32     static assert(isRcPtr!(RcPtr!long));
33     static assert(isRcPtr!(RcPtr!long.WeakType));
34 }
35 
36 
37 
38 /**
39     Implementation of a ref counted pointer without support for aliasing (smaller size of pointer).
40 
41     `RcPtr` retains shared ownership of an object through a pointer.
42         
43     Several ref counted pointer objects may own the same object.
44 
45     The object is destroyed and its memory deallocated when either of the following happens:
46 
47         1. the last remaining ref counted pointer owning the object is destroyed.
48 
49         2. the last remaining ref counted pointer owning the object is assigned another pointer via various methods like `opAssign` and `store`.
50 
51     The object is destroyed using destructor of type `_Type`.
52 
53     A `RcPtr` can not share ownership of an object while storing a pointer to another object (use `SharedPtr` for that).
54     The stored pointer is the one accessed by `get()`, the dereference and the comparison operators.
55 
56     A `RcPtr` may also own no objects, in which case it is called empty.
57 
58     If template parameter `_ControlType` is `shared`  then all member functions (including copy constructor and copy assignment)
59     can be called by multiple threads on different instances of `RcPtr` without additional synchronization even if these instances are copies and share ownership of the same object.
60 
61     If multiple threads of execution access the same `RcPtr` (`shared RcPtr`) then only some methods can be called (`load`, `store`, `exchange`, `compareExchange`, `useCount`).
62 
63     Template parameters:
64 
65         `_Type` type of managed object
66 
67         `_DestructorType` function pointer with attributes of destructor, to get attributes of destructor from type use `btl.autoptr.common.DestructorType!T`. Destructor of type `_Type` must be compatible with `_DestructorType`
68 
69         `_ControlType` represent type of counter, must by of type `btl.autoptr.common.ControlBlock`. if is shared then ref counting is atomic.
70 
71         `_weakPtr` if `true` then `RcPtr` represent weak ptr
72 
73 */
74 public template RcPtr(
75     _Type,
76     _DestructorType = DestructorType!_Type,
77     _ControlType = ControlBlockDeduction!(_Type, SharedControlBlock),
78     bool _weakPtr = false
79 )
80 if(isControlBlock!_ControlType && isDestructorType!_DestructorType){
81 
82     static assert(_ControlType.hasSharedCounter || is(_ControlType == immutable),
83         "_ControlType must be `ControlBlock` with shared counter or `btl.autoptr.common.ControlBlock` must be immutable."
84     );
85 
86     static assert(!_weakPtr || _ControlType.hasWeakCounter,
87         "weak pointer must have control block with weak counter"
88     );
89 
90     static if (is(_Type == class) || is(_Type == interface) || is(_Type == struct) || is(_Type == union))
91         static assert(!__traits(isNested, _Type),
92             "RcPtr does not support nested types."
93         );
94 
95     static assert(is(DestructorType!void : _DestructorType),
96         _Type.stringof ~ " wrong DestructorType " ~ DestructorType!void.stringof ~
97         " : " ~ _DestructorType.stringof
98     );
99 
100     /*
101     static assert(is(DestructorType!_Type : _DestructorType),
102         "destructor of type '" ~ _Type.stringof ~
103         "' doesn't support specified finalizer " ~ _DestructorType.stringof
104     );
105     */
106 
107     void check_dtor()(){
108         static assert(!isIntrusive!_Type);
109 
110         static assert(is(DestructorType!_Type : _DestructorType),
111             "destructor of type '" ~ _Type.stringof ~
112             "' doesn't support specified finalizer " ~ _DestructorType.stringof
113         );
114     }
115 
116     import std.meta : AliasSeq;
117     import std.range : ElementEncodingType;
118     import std.traits: Unqual, Unconst, CopyTypeQualifiers, CopyConstness,
119         hasIndirections, hasElaborateDestructor,
120         isMutable, isAbstractClass, isDynamicArray, isStaticArray, isCallable, Select, isArray;
121 
122     import core.atomic : MemoryOrder;
123     import core.lifetime : forward;
124 
125 
126     enum bool hasWeakCounter = _ControlType.hasWeakCounter;
127 
128     enum bool hasSharedCounter = _ControlType.hasSharedCounter;
129 
130     enum bool referenceElementType = isClassOrInterface!_Type || isDynamicArray!_Type;
131 
132 
133     enum bool _isLockFree = !isDynamicArray!_Type;
134 
135     struct RcPtr{
136 
137         /**
138             Type of element managed by `RcPtr`.
139         */
140         public alias ElementType = _Type;
141 
142 
143         /**
144             Type of destructor (`void function(void*)@attributes`).
145         */
146         public alias DestructorType = _DestructorType;
147 
148 
149         /**
150             Type of control block.
151         */
152         public alias ControlType = _ControlType;
153 
154 
155         /**
156             `true` if `RcPtr` is weak ptr.
157         */
158         public alias isWeak = _weakPtr;
159 
160 
161         /**
162             Same as `ElementType*` or `ElementType` if is class/interface/slice.
163         */
164         public alias ElementReferenceType = ElementReferenceTypeImpl!ElementType;
165 
166 
167         /**
168             Weak pointer
169 
170             `RcPtr.WeakType` is a smart pointer that holds a non-owning ("weak") reference to an object that is managed by `RcPtr`.
171             It must be converted to `RcPtr` in order to access the referenced object.
172 
173             `RcPtr.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,
174             `RcPtr.WeakType` is used to track the object, and it is converted to `RcPtr` to assume temporary ownership.
175             If the original `RcPtr` is destroyed at this time, the object's lifetime is extended until the temporary `RcPtr` is destroyed as well.
176 
177             Another use for `RcPtr.WeakType` is to break reference cycles formed by objects managed by `RcPtr`.
178             If such cycle is orphaned (i,e. there are no outside shared pointers into the cycle), the `RcPtr` reference counts cannot reach zero and the memory is leaked.
179             To prevent this, one of the pointers in the cycle can be made weak.
180         */
181         static if(hasWeakCounter)
182             public alias WeakType = RcPtr!(
183                 _Type,
184                 _DestructorType,
185                 _ControlType,
186                 true
187             );
188         else
189             public alias WeakType = void;
190 
191 
192         /**
193             Type of non weak ptr.
194         */
195         public alias SharedType = RcPtr!(
196             _Type,
197             _DestructorType,
198             _ControlType,
199             false
200         );
201 
202 
203         /**
204             `true` if shared `RcPtr` has lock free operations `store`, `load`, `exchange`, `compareExchange`, otherwise 'false'
205         */
206         public alias isLockFree = _isLockFree;
207 
208         static if(isLockFree)
209             static assert(ElementReferenceType.sizeof == size_t.sizeof);
210 
211 
212 
213         /**
214             Destructor
215 
216             If `this` owns an object and it is the last `RcPtr` owning it, the object is destroyed.
217             After the destruction, the smart pointers that shared ownership with `this`, if any, will report a `useCount()` that is one less than its previous value.
218         */
219         public ~this(){
220             this._release();
221         }
222 
223 
224         //necesary for btl.autoptr.unique_ptr.sharedPtr
225         package this(Elm, this This)(Elm element, Forward)pure nothrow @safe @nogc
226         if(true
227             && is(Elm : GetElementReferenceType!This) 
228             && !is(Unqual!Elm == typeof(null))
229         ){
230             this._element = element;
231         }
232 
233         //
234         package this(C, Elm, this This)(C* control, Elm element)pure nothrow @safe @nogc
235         if(true
236             && is(Elm : GetElementReferenceType!This) 
237             && is(C : GetControlType!This) 
238             && !is(Unqual!Elm == typeof(null))
239         ){
240             assert(control !is null);
241             assert((control is null) == (element is null));
242 
243             this(element, Forward.init);
244             control.add!isWeak;
245         }
246 
247 
248         /**
249             Forward constructor (merge move and copy constructor).
250         */
251         public this(Rhs, this This)(scope auto ref Rhs rhs, Forward)@trusted
252         if(isRcPtr!Rhs && !is(Rhs == shared)){
253             //error:
254             static if(!isConstructable!(rhs, This)){
255                 this.construct_error(forward!rhs);
256             }
257             //lock (copy):
258             else static if(weakLock!(Rhs, This)){
259                 if(rhs._element !is null && rhs._control.add_shared_if_exists())
260                     this._element = rhs._element;
261                 /+else
262                     this._element = null;+/
263             }
264             //copy
265             else static if(isRef!rhs){
266                 static assert(isCopyConstructable!(Rhs, This));
267 
268                 if(rhs._element is null)
269                     this(null);
270                 else
271                     this(rhs._control, rhs._element);
272             }
273             //move
274             else{
275                 static assert(isMoveConstructable!(Rhs, This));
276 
277                 this._element = rhs._element;
278 
279                 static if(isWeak && !Rhs.isWeak){
280                     if(this._element !is null)
281                         this._control.add!isWeak;
282                 }
283                 else{
284                     rhs._const_reset();
285                 }
286             }
287         }
288 
289         //
290         private void construct_error(Rhs, this This)(scope auto ref Rhs rhs)
291         if(isRcPtr!Rhs && !isConstructable!(rhs, This)){
292             static if(isRef!rhs){
293                 import std.traits : isMutable;
294 
295                 static assert(isMutable!Rhs,
296                     "rhs must be mutable."
297                 );
298                 static assert(isMutable!(Rhs.ControlType),
299                     "control type of rhs must be mutable."
300                 );
301             }
302 
303             static assert(is(GetElementReferenceType!Rhs : GetElementReferenceType!This),
304                 "element type '" ~ GetElementReferenceType!Rhs.stringof ~ "' is not compatible with '" ~ GetElementReferenceType!This.stringof ~ "'."
305             );
306             static assert(is(Rhs.DestructorType : This.DestructorType),
307                 "destructor attributes '" ~ Rhs.DestructorType.stringof ~ "' are not compatible with '" ~ This.DestructorType.stringof ~ "'."
308             );
309             static assert(is(GetControlType!Rhs* : GetControlType!This*),
310                 "control type " ~ GetControlType!Rhs.stringof ~ " is not compatible with '" ~ GetControlType!This.stringof ~ "'."
311             );
312 
313             static assert(0, "RcPtr canno't be constructed from rhs of type " ~ Rhs.stringof);
314         }
315 
316 
317         /**
318             Constructs a `RcPtr` without managed object. Same as `RcPtr.init`
319 
320             Examples:
321                 --------------------
322                 RcPtr!long x = null;
323 
324                 assert(x == null);
325                 assert(x == RcPtr!long.init);
326                 --------------------
327         */
328         public this(this This)(typeof(null) nil, Forward = Forward.init)pure nothrow @safe @nogc{
329         }
330 
331 
332 
333         /**
334             Constructs a `RcPtr` which shares ownership of the object managed by `rhs`.
335 
336             If rhs manages no object, this manages no object too.
337             If rhs if rvalue then ownership is moved.
338             The template overload doesn't participate in overload resolution if ElementType of `typeof(rhs)` is not implicitly convertible to `ElementType`.
339             If rhs if `WeakType` then this ctor is equivalent to `this(rhs.lock())`.
340 
341             Examples:
342                 --------------------
343                 {
344                     RcPtr!long x = RcPtr!long.make(123);
345                     assert(x.useCount == 1);
346 
347                     RcPtr!long a = x;         //lvalue copy ctor
348                     assert(a == x);
349 
350                     const RcPtr!long b = x;   //lvalue copy ctor
351                     assert(b == x);
352 
353                     RcPtr!(const long) c = x; //lvalue ctor
354                     assert(c == x);
355 
356                     const RcPtr!long d = b;   //lvalue ctor
357                     assert(d == x);
358 
359                     assert(x.useCount == 5);
360                 }
361 
362                 {
363                     import core.lifetime : move;
364                     RcPtr!long x = RcPtr!long.make(123);
365                     assert(x.useCount == 1);
366 
367                     RcPtr!long a = move(x);        //rvalue copy ctor
368                     assert(a.useCount == 1);
369 
370                     const RcPtr!long b = move(a);  //rvalue copy ctor
371                     assert(b.useCount == 1);
372 
373                     RcPtr!(const long) c = b.load;  //rvalue ctor
374                     assert(c.useCount == 2);
375 
376                     const RcPtr!long d = move(c);  //rvalue ctor
377                     assert(d.useCount == 2);
378                 }
379 
380                 {
381                     import core.lifetime : move;
382                     auto u = UniquePtr!(long, SharedControlBlock).make(123);
383 
384                     RcPtr!long s = move(u);        //rvalue copy ctor
385                     assert(s != null);
386                     assert(s.useCount == 1);
387 
388                     RcPtr!long s2 = UniquePtr!(long, SharedControlBlock).init;
389                     assert(s2 == null);
390                 }
391                 --------------------
392         */
393         public this(Rhs, this This)(scope auto ref Rhs rhs)@trusted
394         if(isRcPtr!Rhs && !is(Rhs == shared) && !isMoveCtor!(This, rhs)){
395             //static assert(isConstructable!(rhs, This));
396             this(forward!rhs, Forward.init);
397         }
398 
399 
400 
401         //copy ctors:
402         static if(isCopyConstructable!(typeof(this), typeof(this)))
403             this(ref scope typeof(this) rhs)@safe{this(rhs, Forward.init);}
404         else
405             @disable this(ref scope typeof(this) rhs)@safe;
406 
407         static if(isCopyConstructable!(typeof(this), const typeof(this)))
408             this(ref scope typeof(this) rhs)const @safe{this(rhs, Forward.init);}
409         else
410             @disable this(ref scope typeof(this) rhs)const @safe;
411 
412         static if(isCopyConstructable!(typeof(this), immutable typeof(this)))
413             this(ref scope typeof(this) rhs)immutable @safe{this(rhs, Forward.init);}
414         else
415             @disable this(ref scope typeof(this) rhs)immutable @safe;
416 
417         static if(isCopyConstructable!(typeof(this), shared typeof(this)))
418             this(ref scope typeof(this) rhs)shared @safe{this(rhs, Forward.init);}
419         else
420             @disable this(ref scope typeof(this) rhs)shared @safe;
421 
422         static if(isCopyConstructable!(typeof(this), const shared typeof(this)))
423             this(ref scope typeof(this) rhs)const shared @safe{this(rhs, Forward.init);}
424         else
425             @disable this(ref scope typeof(this) rhs)const shared @safe;
426 
427 
428         /+
429         //Not neccesary:
430         static foreach(alias From; AliasSeq!(
431             const typeof(this),
432             immutable typeof(this),
433             shared typeof(this),
434             const shared typeof(this)
435         )){
436             @disable this(ref scope From rhs)@safe;
437             @disable this(ref scope From rhs)const @safe;
438             @disable this(ref scope From rhs)immutable @safe;
439             @disable this(ref scope From rhs)shared @safe;
440             @disable this(ref scope From rhs)const shared @safe;
441             //@disable this(ref scope From rhs)pure nothrow @safe @nogc;
442         }
443         +/
444 
445 
446 
447         /**
448             Releases the ownership of the managed object, if any.
449 
450             After the call, this manages no object.
451 
452             Examples:
453                 --------------------
454                 {
455                     RcPtr!long x = RcPtr!long.make(1);
456 
457                     assert(x.useCount == 1);
458                     x = null;
459                     assert(x.useCount == 0);
460                     assert(x == null);
461                 }
462 
463                 {
464                     RcPtr!(shared long) x = RcPtr!(shared long).make(1);
465 
466                     assert(x.useCount == 1);
467                     x = null;
468                     assert(x.useCount == 0);
469                     assert(x == null);
470                 }
471 
472                 {
473                     shared RcPtr!(long) x = RcPtr!(shared long).make(1);
474 
475                     assert(x.useCount == 1);
476                     x = null;
477                     assert(x.useCount == 0);
478                     assert(x == null);
479                 }
480                 --------------------
481         */
482         public void opAssign(MemoryOrder order = MemoryOrder.seq, this This)(typeof(null) nil)scope
483         if(isMutable!This){
484             static if(is(This == shared)){
485                 static if(isLockFree){
486                     import core.atomic : atomicExchange;
487 
488                     ()@trusted{
489                         UnqualSmartPtr!This tmp;
490                         tmp._set_element(cast(typeof(this._element))atomicExchange!order(
491                             cast(Unqual!(This.ElementReferenceType)*)&this._element,
492                             null
493                         ));
494                     }();
495                 }
496                 else{
497                     return this.lockSmartPtr!(
498                         (ref scope self) => self.opAssign!order(null)
499                     )();
500                 }
501             }
502             else{
503                 this._release();
504                 ()@trusted{
505                     this._reset();
506                 }();
507             }
508         }
509 
510         /**
511             Shares ownership of the object managed by `rhs`.
512 
513             If `rhs` manages no object, `this` manages no object too.
514             If `rhs` is rvalue then move-assigns a `RcPtr` from `rhs`
515 
516             Examples:
517                 --------------------
518                 {
519                     RcPtr!long px1 = RcPtr!long.make(1);
520                     RcPtr!long px2 = RcPtr!long.make(2);
521 
522                     assert(px2.useCount == 1);
523                     px1 = px2;
524                     assert(*px1 == 2);
525                     assert(px2.useCount == 2);
526                 }
527 
528 
529                 {
530                     RcPtr!long px = RcPtr!long.make(1);
531                     RcPtr!(const long) pcx = RcPtr!long.make(2);
532 
533                     assert(px.useCount == 1);
534                     pcx = px;
535                     assert(*pcx == 1);
536                     assert(pcx.useCount == 2);
537 
538                 }
539 
540 
541                 {
542                     const RcPtr!long cpx = RcPtr!long.make(1);
543                     RcPtr!(const long) pcx = RcPtr!long.make(2);
544 
545                     assert(pcx.useCount == 1);
546                     pcx = cpx;
547                     assert(*pcx == 1);
548                     assert(pcx.useCount == 2);
549 
550                 }
551 
552                 {
553                     RcPtr!(immutable long) pix = RcPtr!(immutable long).make(123);
554                     RcPtr!(const long) pcx = RcPtr!long.make(2);
555 
556                     assert(pix.useCount == 1);
557                     pcx = pix;
558                     assert(*pcx == 123);
559                     assert(pcx.useCount == 2);
560 
561                 }
562                 --------------------
563         */
564         public void opAssign(MemoryOrder order = MemoryOrder.seq, Rhs, this This)(scope auto ref Rhs desired)scope
565         if(isRcPtr!Rhs && !is(Rhs == shared)){
566             //error
567             static if(!isAssignable!(desired, This)){
568                 this.assign_error(forward!desired);
569             }
570             // shared assign:
571             else static if(is(This == shared)){
572                 static if(isLockFree){
573                     import core.atomic : atomicExchange;
574 
575                     static if(isRef!desired && (This.isWeak == Rhs.isWeak)){
576                         if((()@trusted => cast(const void*)&desired is cast(const void*)&this)())
577                             return;
578                     }
579 
580                     ()@trusted{
581                         UnqualSmartPtr!This tmp_desired = forward!desired;
582                         //desired._control.add!(This.isWeak);
583 
584                         UnqualSmartPtr!This tmp;
585                         GetElementReferenceType!This source = tmp_desired._element;    //interface/class cast
586 
587                         tmp._set_element(cast(typeof(this._element))atomicExchange!order(
588                             cast(Unqual!(This.ElementReferenceType)*)&this._element,
589                             cast(Unqual!(This.ElementReferenceType))source
590                         ));
591 
592                         tmp_desired._const_reset();
593                     }();
594                 }
595                 else{
596                     this.lockSmartPtr!(
597                         (ref scope self, scope auto ref Rhs x) => self.opAssign!order(forward!x)
598                     )(forward!desired);
599                 }
600             }
601             // copy assign or non identity move assign:
602             else static if(isRef!desired || !is(This == Rhs)){
603 
604                 static if(isRef!desired && (This.isWeak == Rhs.isWeak)){
605                     if((()@trusted => cast(const void*)&desired is cast(const void*)&this)())
606                         return;
607                 }
608 
609                 this._release();
610 
611                 auto tmp = This(forward!desired);
612 
613                 ()@trusted{
614                     this._set_element(tmp._element);
615                     tmp._const_reset();
616                 }();
617             }
618             //identity move assign:   //separate case for core.lifetime.move
619             else{
620                 static assert(isMoveAssignable!(Rhs, This));
621                 static assert(!isRef!desired);
622 
623                 this._release();
624 
625                 ()@trusted{
626                     this._set_element(desired._element);
627                     desired._const_reset();
628                 }();
629 
630             }
631         }
632 
633         //
634         private void assign_error(Rhs, this This)(scope auto ref Rhs desired)
635         if(isRcPtr!Rhs && !isAssignable!(desired, This)){
636             import std.traits : isMutable;
637 
638             static assert(!weakLock!(Rhs, This),
639                 "weak error"
640             );
641             static assert(isMutable!This, "assign must have mutable this");
642 
643 
644             this.construct_error(forward!desired);
645         }
646 
647 
648 
649         /**
650             Constructs an object of type `ElementType` and wraps it in a `RcPtr` using args as the parameter list for the constructor of `ElementType`.
651 
652             The object is constructed as if by the expression `emplace!ElementType(_payload, forward!args)`, where _payload is an internal pointer to storage suitable to hold an object of type `ElementType`.
653             The storage is typically larger than `ElementType.sizeof` in order to use one allocation for both the control block and the `ElementType` object.
654 
655             Examples:
656                 --------------------
657                 {
658                     RcPtr!long a = RcPtr!long.make();
659                     assert(a.get == 0);
660 
661                     RcPtr!(const long) b = RcPtr!long.make(2);
662                     assert(b.get == 2);
663                 }
664 
665                 {
666                     static struct Struct{
667                         int i = 7;
668 
669                         this(int i)pure nothrow @safe @nogc{
670                             this.i = i;
671                         }
672                     }
673 
674                     RcPtr!Struct s1 = RcPtr!Struct.make();
675                     assert(s1.get.i == 7);
676 
677                     RcPtr!Struct s2 = RcPtr!Struct.make(123);
678                     assert(s2.get.i == 123);
679                 }
680 
681                 {
682                     static interface Interface{
683                     }
684                     static class Class : Interface{
685                         int i;
686 
687                         this(int i)pure nothrow @safe @nogc{
688                             this.i = i;
689                         }
690                     }
691 
692                     RcPtr!Interface x = RcPtr!Class.make(3);
693                     //assert(x.dynTo!Class.get.i == 3);
694                 }
695                 --------------------
696         */
697         public static auto make(AllocatorType = DefaultAllocator, bool supportGC = platformSupportGC, Args...)(auto ref Args args)
698         if(!isDynamicArray!ElementType){
699             check_dtor();
700 
701             alias ReturnType = RcPtr!(
702                 ElementType,
703                 .DestructorType!(
704                     .DestructorType!ElementType,
705                     DestructorType,
706                     DestructorAllocatorType!AllocatorType
707                 ),
708                 ControlType
709             );
710 
711             auto m = ReturnType.MakeEmplace!(AllocatorType, supportGC).make(AllocatorType.init, forward!(args));
712 
713             return (m is null)
714                 ? ReturnType.init
715                 : ReturnType(m.get, Forward.init);
716         }
717 
718 
719         /**
720             Constructs an object of array type `ElementType` including its array elements and wraps it in a `RcPtr`.
721 
722             Parameters:
723                 n = Array length
724 
725                 args = parameters for constructor for each array element.
726 
727             The array elements are constructed as if by the expression `emplace!ElementType(_payload, args)`, where _payload is an internal pointer to storage suitable to hold an object of type `ElementType`.
728             The storage is typically larger than `ElementType.sizeof * n` in order to use one allocation for both the control block and the each array element.
729 
730             Examples:
731                 --------------------
732                 auto arr = RcPtr!(long[]).make(6, -1);
733                 assert(arr.length == 6);
734                 assert(arr.get.length == 6);
735 
736                 import std.algorithm : all;
737                 assert(arr.get.all!(x => x == -1));
738 
739                 for(int i = 0; i < 6; ++i)
740                     arr.get[i] = i;
741 
742                 assert(arr.get == [0, 1, 2, 3, 4, 5]);
743                 --------------------
744         */
745         public static auto make(AllocatorType = DefaultAllocator, bool supportGC = platformSupportGC, Args...)(const size_t n, auto ref Args args)
746         if(isDynamicArray!ElementType){
747             check_dtor();
748 
749             alias ReturnType = RcPtr!(
750                 ElementType,
751                 .DestructorType!(
752                     .DestructorType!ElementType,
753                     DestructorType,
754                     DestructorAllocatorType!AllocatorType
755                 ),
756                 ControlType
757             );
758 
759             auto m = ReturnType.MakeDynamicArray!(AllocatorType, supportGC).make(AllocatorType.init, n, forward!(args));
760 
761             return (m is null)
762                 ? ReturnType.init
763                 : ReturnType(m.get, Forward.init);
764         }
765 
766 
767 
768         /**
769             Constructs an object of type `ElementType` and wraps it in a `RcPtr` using args as the parameter list for the constructor of `ElementType`.
770 
771             The object is constructed as if by the expression `emplace!ElementType(_payload, forward!args)`, where _payload is an internal pointer to storage suitable to hold an object of type `ElementType`.
772             The storage is typically larger than `ElementType.sizeof` in order to use one allocation for both the control block and the `ElementType` object.
773 
774             Examples:
775                 --------------------
776                 auto a = allocatorObject(Mallocator.instance);
777                 {
778                     auto a = RcPtr!long.alloc(a);
779                     assert(a.get == 0);
780 
781                     auto b = RcPtr!(const long).alloc(a, 2);
782                     assert(b.get == 2);
783                 }
784 
785                 {
786                     static struct Struct{
787                         int i = 7;
788 
789                         this(int i)pure nothrow @safe @nogc{
790                             this.i = i;
791                         }
792                     }
793 
794                     auto s1 = RcPtr!Struct.alloc(a);
795                     assert(s1.get.i == 7);
796 
797                     auto s2 = RcPtr!Struct.alloc(a, 123);
798                     assert(s2.get.i == 123);
799                 }
800 
801                 {
802                     static interface Interface{
803                     }
804                     static class Class : Interface{
805                         int i;
806 
807                         this(int i)pure nothrow @safe @nogc{
808                             this.i = i;
809                         }
810                     }
811 
812                     RcPtr!Interface x = RcPtr!Class.alloc(a, 3);
813                     //assert(x.dynTo!Class.get.i == 3);
814                 }
815                 --------------------
816         */
817         public static auto alloc(bool supportGC = platformSupportGC, AllocatorType, Args...)(AllocatorType a, auto ref Args args)
818         if(!isDynamicArray!ElementType){
819             check_dtor();
820 
821             alias ReturnType = RcPtr!(
822                 ElementType,
823                 .DestructorType!(
824                     .DestructorType!ElementType,
825                     DestructorType,
826                     DestructorAllocatorType!AllocatorType
827                 ),
828                 ControlType
829             );
830             auto m = ReturnType.MakeEmplace!(AllocatorType, supportGC).make(forward!(a, args));
831 
832             return (m is null)
833                 ? ReturnType.init
834                 : ReturnType(m.get, Forward.init);
835         }
836 
837 
838 
839         /**
840             Constructs an object of array type `ElementType` including its array elements and wraps it in a `RcPtr`.
841 
842             Parameters:
843                 n = Array length
844 
845                 args = parameters for constructor for each array element.
846 
847             The array elements are constructed as if by the expression `emplace!ElementType(_payload, args)`, where _payload is an internal pointer to storage suitable to hold an object of type `ElementType`.
848             The storage is typically larger than `ElementType.sizeof * n` in order to use one allocation for both the control block and the each array element.
849 
850             Examples:
851                 --------------------
852                 auto a = allocatorObject(Mallocator.instance);
853                 auto arr = RcPtr!(long[], DestructorType!(typeof(a))).alloc(a, 6, -1);
854                 assert(arr.length == 6);
855                 assert(arr.get.length == 6);
856 
857                 import std.algorithm : all;
858                 assert(arr.get.all!(x => x == -1));
859 
860                 for(int i = 0; i < 6; ++i)
861                     arr.get[i] = i;
862 
863                 assert(arr.get == [0, 1, 2, 3, 4, 5]);
864                 --------------------
865         */
866         public static auto alloc(bool supportGC = platformSupportGC, AllocatorType, Args...)(AllocatorType a, const size_t n, auto ref Args args)
867         if(isDynamicArray!ElementType){
868             check_dtor();
869 
870             alias ReturnType = RcPtr!(
871                 ElementType,
872                 .DestructorType!(
873                     .DestructorType!ElementType,
874                     DestructorType,
875                     DestructorAllocatorType!AllocatorType
876                 ),
877                 ControlType
878             );
879 
880             auto m = ReturnType.MakeDynamicArray!(AllocatorType, supportGC).make(forward!(a, n, args));
881 
882             return (m is null)
883                 ? ReturnType.init
884                 : ReturnType(m.get, Forward.init);
885         }
886 
887 
888 
889         /**
890             Returns the number of different `RcPtr` instances
891 
892             Returns the number of different `RcPtr` instances (`this` included) managing the current object or `0` if there is no managed object.
893 
894             Examples:
895                 --------------------
896                 RcPtr!long x = null;
897 
898                 assert(x.useCount == 0);
899 
900                 x = RcPtr!long.make(123);
901                 assert(x.useCount == 1);
902 
903                 auto y = x;
904                 assert(x.useCount == 2);
905 
906                 auto w1 = x.weak;    //weak ptr
907                 assert(x.useCount == 2);
908 
909                 RcPtr!long.WeakType w2 = x;   //weak ptr
910                 assert(x.useCount == 2);
911 
912                 y = null;
913                 assert(x.useCount == 1);
914 
915                 x = null;
916                 assert(x.useCount == 0);
917                 assert(w1.useCount == 0);
918                 --------------------
919         */
920         public @property ControlType.Shared useCount(this This)()const scope nothrow @trusted @nogc{
921 
922             static if(is(ControlType.Shared == void))
923                 return;
924 
925             else static if(is(This == shared))
926                 return this.lockSmartPtr!(
927                     (ref scope self) => self.useCount()
928                 )();
929 
930             else
931                 return (this._element is null)
932                     ? 0
933                     : this._control.count!false + 1;
934             
935 
936         }
937 
938 
939         /**
940             Returns the number of different `RcPtr.WeakType` instances
941 
942             Returns the number of different `RcPtr.WeakType` instances (`this` included) managing the current object or `0` if there is no managed object.
943 
944             Examples:
945                 --------------------
946                 RcPtr!long x = null;
947                 assert(x.useCount == 0);
948                 assert(x.weakCount == 0);
949 
950                 x = RcPtr!long.make(123);
951                 assert(x.useCount == 1);
952                 assert(x.weakCount == 0);
953 
954                 auto w = x.weak();
955                 assert(x.useCount == 1);
956                 assert(x.weakCount == 1);
957                 --------------------
958         */
959         public @property ControlType.Weak weakCount(this This)()const scope nothrow @safe @nogc{
960 
961             static if(is(ControlType.Weak == void))
962                 return;
963 
964             else static if(is(This == shared))
965                 return this.lockSharedPtr!(
966                     (ref scope self) => self.weakCount()
967                 )();
968             
969             else
970                 return (this._element is null)
971                     ? 0
972                     : this._control.count!true;
973             
974 
975         }
976 
977 
978 
979         /**
980             Swap `this` with `rhs`
981 
982             Examples:
983                 --------------------
984                 {
985                     RcPtr!long a = RcPtr!long.make(1);
986                     RcPtr!long b = RcPtr!long.make(2);
987                     a.proxySwap(b);
988                     assert(*a == 2);
989                     assert(*b == 1);
990                     import std.algorithm : swap;
991                     swap(a, b);
992                     assert(*a == 1);
993                     assert(*b == 2);
994                     assert(a.useCount == 1);
995                     assert(b.useCount == 1);
996                 }
997                 --------------------
998         */
999         public void proxySwap(ref scope typeof(this) rhs)scope @trusted pure nothrow @nogc{
1000             auto element = this._element;
1001             this._set_element(rhs._element);
1002             rhs._set_element(element);
1003         }
1004 
1005 
1006 
1007         /**
1008             Returns the non `shared` `RcPtr` pointer pointed-to by `shared` `this`.
1009 
1010             Examples:
1011                 --------------------
1012                 shared RcPtr!(long) x = RcPtr!(shared long).make(123);
1013 
1014                 {
1015                     RcPtr!(shared long) y = x.load();
1016                     assert(y.useCount == 2);
1017 
1018                     assert(y.get == 123);
1019                 }
1020                 --------------------
1021         */
1022         public UnqualSmartPtr!This load(MemoryOrder order = MemoryOrder.seq, this This)()scope{
1023 
1024             static if(is(This == shared))
1025                 return this.lockSmartPtr!(
1026                     (ref scope self) => self.load!order()
1027                 )();
1028             
1029             else
1030                 return typeof(return)(this);
1031             
1032         }
1033 
1034 
1035 
1036         /**
1037             Stores the non `shared` `RcPtr` parameter `ptr` to `this`.
1038 
1039             If `this` is shared then operation is atomic or guarded by mutex.
1040 
1041             Template parameter `order` has type `core.atomic.MemoryOrder`.
1042 
1043             Examples:
1044                 --------------------
1045                 //null store:
1046                 {
1047                     shared x = RcPtr!(shared long).make(123);
1048                     assert(x.load.get == 123);
1049 
1050                     x.store(null);
1051                     assert(x.useCount == 0);
1052                     assert(x.load == null);
1053                 }
1054 
1055                 //rvalue store:
1056                 {
1057                     shared x = RcPtr!(shared long).make(123);
1058                     assert(x.load.get == 123);
1059 
1060                     x.store(RcPtr!(shared long).make(42));
1061                     assert(x.load.get == 42);
1062                 }
1063 
1064                 //lvalue store:
1065                 {
1066                     shared x = RcPtr!(shared long).make(123);
1067                     auto y = RcPtr!(shared long).make(42);
1068 
1069                     assert(x.load.get == 123);
1070                     assert(y.load.get == 42);
1071 
1072                     x.store(y);
1073                     assert(x.load.get == 42);
1074                     assert(x.useCount == 2);
1075                 }
1076                 --------------------
1077         */
1078         public alias store = opAssign;
1079 
1080 
1081 
1082         /**
1083             Stores the non `shared` `RcPtr` pointer ptr in the `shared(RcPtr)` pointed to by `this` and returns the value formerly pointed-to by this, atomically or with mutex.
1084 
1085             Examples:
1086                 --------------------
1087                 //lvalue exchange
1088                 {
1089                     shared x = RcPtr!(shared long).make(123);
1090                     auto y = RcPtr!(shared long).make(42);
1091 
1092                     auto z = x.exchange(y);
1093 
1094                     assert(x.load.get == 42);
1095                     assert(y.get == 42);
1096                     assert(z.get == 123);
1097                 }
1098 
1099                 //rvalue exchange
1100                 {
1101                     shared x = RcPtr!(shared long).make(123);
1102                     auto y = RcPtr!(shared long).make(42);
1103 
1104                     import core.lifetime : move;
1105                     auto z = x.exchange(move(y));
1106 
1107                     assert(x.load.get == 42);
1108                     assert(y == null);
1109                     assert(z.get == 123);
1110                 }
1111 
1112                 //null exchange (same as move)
1113                 {
1114                     shared x = RcPtr!(shared long).make(123);
1115 
1116                     auto z = x.exchange(null);
1117 
1118                     assert(x.load == null);
1119                     assert(z.get == 123);
1120                 }
1121 
1122                 //swap:
1123                 {
1124                     shared x = RcPtr!(shared long).make(123);
1125                     auto y = RcPtr!(shared long).make(42);
1126 
1127                     import core.lifetime : move;
1128                     //opAssign is same as store
1129                     y = x.exchange(move(y));
1130 
1131                     assert(x.load.get == 42);
1132                     assert(y.get == 123);
1133                 }
1134                 --------------------
1135         */
1136         public RcPtr exchange(MemoryOrder order = MemoryOrder.seq, this This)(typeof(null))scope
1137         if(isMutable!This){
1138 
1139             static if(is(This == shared)){
1140                 static if(isLockFree){
1141                     import core.atomic : atomicExchange;
1142 
1143                     return()@trusted{
1144                         UnqualSmartPtr!This result;
1145                         result._set_element(cast(typeof(this._element))atomicExchange!order(
1146                             cast(Unqual!(This.ElementReferenceType)*)&this._element,
1147                             null
1148                         ));
1149 
1150                         return result._move;
1151                     }();
1152                 }
1153                 else{
1154                     return this.lockSmartPtr!(
1155                         (ref scope self) => self.exchange!order(null)
1156                     )();
1157                 }
1158             }
1159             else{
1160                 return this._move;
1161             }
1162         }
1163 
1164         /// ditto
1165         public RcPtr exchange(MemoryOrder order = MemoryOrder.seq, Rhs, this This)(scope Rhs rhs)scope
1166         if(    isRcPtr!Rhs
1167             && isMoveAssignable!(Rhs, This)
1168             && !is(Rhs == shared)
1169         ){
1170             static if(is(This == shared)){
1171 
1172                 static if(isLockFree){
1173                     import core.atomic : atomicExchange;
1174 
1175                     return()@trusted{
1176                         UnqualSmartPtr!This result;
1177                         GetElementReferenceType!This source = rhs._element;    //interface/class cast
1178 
1179                         result._set_element(cast(typeof(this._element))atomicExchange!order(
1180                             cast(Unqual!(This.ElementReferenceType)*)&this._element,
1181                             cast(Unqual!(This.ElementReferenceType))source
1182                         ));
1183                         rhs._const_reset();
1184 
1185                         return result._move;
1186                     }();
1187                 }
1188                 else{
1189                     return this.lockSmartPtr!(
1190                         (ref scope self, Rhs x) => self.exchange!order(x._move)
1191                     )(rhs._move);
1192                 }
1193             }
1194             else{
1195                 auto result = this._move;
1196 
1197                 return()@trusted{
1198                     this = rhs._move;
1199                     return result._move;
1200                 }();
1201             }
1202         }
1203 
1204 
1205         /**
1206             Compares the `RcPtr` pointers pointed-to by `this` and `expected`.
1207 
1208             If they are equivalent (store the same pointer value, and either share ownership of the same object or are both empty), assigns `desired` into `this` using the memory ordering constraints specified by `success` and returns `true`.
1209             If they are not equivalent, assigns `this` into `expected` using the memory ordering constraints specified by `failure` and returns `false`.
1210 
1211             More info in c++ std::atomic<std::shared_ptr>.
1212 
1213 
1214             Examples:
1215                 --------------------
1216                 static foreach(enum bool weak; [true, false]){
1217                     //fail
1218                     {
1219                         RcPtr!long a = RcPtr!long.make(123);
1220                         RcPtr!long b = RcPtr!long.make(42);
1221                         RcPtr!long c = RcPtr!long.make(666);
1222 
1223                         static if(weak)a.compareExchangeWeak(b, c);
1224                         else a.compareExchangeStrong(b, c);
1225 
1226                         assert(*a == 123);
1227                         assert(*b == 123);
1228                         assert(*c == 666);
1229 
1230                     }
1231 
1232                     //success
1233                     {
1234                         RcPtr!long a = RcPtr!long.make(123);
1235                         RcPtr!long b = a;
1236                         RcPtr!long c = RcPtr!long.make(666);
1237 
1238                         static if(weak)a.compareExchangeWeak(b, c);
1239                         else a.compareExchangeStrong(b, c);
1240 
1241                         assert(*a == 666);
1242                         assert(*b == 123);
1243                         assert(*c == 666);
1244                     }
1245 
1246                     //shared fail
1247                     {
1248                         shared RcPtr!(shared long) a = RcPtr!(shared long).make(123);
1249                         RcPtr!(shared long) b = RcPtr!(shared long).make(42);
1250                         RcPtr!(shared long) c = RcPtr!(shared long).make(666);
1251 
1252                         static if(weak)a.compareExchangeWeak(b, c);
1253                         else a.compareExchangeStrong(b, c);
1254 
1255                         auto tmp = a.exchange(null);
1256                         assert(*tmp == 123);
1257                         assert(*b == 123);
1258                         assert(*c == 666);
1259                     }
1260 
1261                     //shared success
1262                     {
1263                         RcPtr!(shared long) b = RcPtr!(shared long).make(123);
1264                         shared RcPtr!(shared long) a = b;
1265                         RcPtr!(shared long) c = RcPtr!(shared long).make(666);
1266 
1267                         static if(weak)a.compareExchangeWeak(b, c);
1268                         else a.compareExchangeStrong(b, c);
1269 
1270                         auto tmp = a.exchange(null);
1271                         assert(*tmp == 666);
1272                         assert(*b == 123);
1273                         assert(*c == 666);
1274                     }
1275                 }
1276                 --------------------
1277         */
1278         public bool compareExchangeStrong
1279             (MemoryOrder success = MemoryOrder.seq, MemoryOrder failure = success, E, D, this This)
1280             (ref scope E expected, scope D desired)scope
1281         if(    isRcPtr!E && !is(E == shared)
1282             && isRcPtr!D && !is(D == shared)
1283             && isMoveAssignable!(D, This)
1284             && isCopyAssignable!(This, E)
1285             && (This.isWeak == D.isWeak)
1286             && (This.isWeak == E.isWeak)
1287         ){
1288             return this.compareExchangeImpl!(false, success, failure)(expected, desired._move);
1289         }
1290 
1291 
1292 
1293         /**
1294             Same as `compareExchangeStrong` but may fail spuriously.
1295 
1296             More info in c++ `std::atomic<std::shared_ptr>`.
1297         */
1298         public bool compareExchangeWeak
1299             (MemoryOrder success = MemoryOrder.seq, MemoryOrder failure = success, E, D, this This)
1300             (ref scope E expected, scope D desired)scope
1301         if(    isRcPtr!E && !is(E == shared)
1302             && isRcPtr!D && !is(D == shared)
1303             && isMoveAssignable!(D, This)
1304             && isCopyAssignable!(This, E)
1305             && (This.isWeak == D.isWeak)
1306             && (This.isWeak == E.isWeak)
1307         ){
1308             return this.compareExchangeImpl!(true, success, failure)(expected, desired._move);
1309         }
1310 
1311 
1312         private bool compareExchangeImpl
1313             (bool weak, MemoryOrder success, MemoryOrder failure, E, D, this This)
1314             (ref scope E expected, scope D desired)scope @trusted
1315         if(    isRcPtr!E && !is(E == shared)
1316             && isRcPtr!D && !is(D == shared)
1317             && isMoveAssignable!(D, This)
1318             && isCopyAssignable!(This, E)
1319             && (This.isWeak == D.isWeak)
1320             && (This.isWeak == E.isWeak)
1321         ){
1322             static if(is(This == shared)){
1323                 static if(isLockFree){
1324                     import core.atomic : cas, casWeak;
1325                     static if(weak)
1326                         alias casImpl = casWeak;
1327                     else
1328                         alias casImpl = cas;
1329 
1330 
1331                     return ()@trusted{
1332                         GetElementReferenceType!This source_desired = desired._element;     //interface/class cast
1333                         GetElementReferenceType!This source_expected = expected._element;   //interface/class cast
1334 
1335                         const bool store_occurred = casImpl!(success, failure)(
1336                             cast(Unqual!(This.ElementReferenceType)*)&this._element,
1337                             cast(Unqual!(This.ElementReferenceType)*)&source_expected,
1338                             cast(Unqual!(This.ElementReferenceType))source_desired
1339                         );
1340 
1341                         if(store_occurred){
1342                             desired._const_reset();
1343                             if(expected._element !is null)
1344                                 expected._control.release!(This.isWeak);
1345                         }
1346                         else{
1347                             expected = null;
1348                             expected._set_element(source_expected);
1349                         }
1350 
1351                         return store_occurred;
1352                     }();
1353                 }
1354                 else{
1355                     static assert(!isLockFree);
1356                     shared mutex = getMutex(this);
1357 
1358                     mutex.lock();
1359 
1360                     alias Self = UnqualSmartPtr!This;
1361 
1362                     static assert(!is(Self == shared));
1363 
1364                     Self* self = cast(Self*)&this;
1365 
1366                     if(*self == expected){
1367                         auto tmp = self._move;   //destructor is called after  mutex.unlock();
1368                         *self = desired._move;
1369 
1370                         mutex.unlock();
1371                         return true;
1372                     }
1373 
1374                     auto tmp = expected._move;   //destructor is called after  mutex.unlock();
1375                     expected = *self;
1376 
1377                     mutex.unlock();
1378                     return false;
1379                 }
1380             }
1381             else{
1382                 if(this == expected){
1383                     this = desired._move;
1384                     return true;
1385                 }
1386                 expected = this;
1387 
1388                 return false;
1389             }
1390         }
1391 
1392 
1393 
1394         /**
1395             Creates a new non weak `RcPtr` that shares ownership of the managed object (must be `RcPtr.WeakType`).
1396 
1397             If there is no managed object, i.e. this is empty or this is `expired`, then the returned `RcPtr` is empty.
1398             Method exists only if `RcPtr` is `isWeak`
1399 
1400             Examples:
1401                 --------------------
1402                 {
1403                     RcPtr!long x = RcPtr!long.make(123);
1404 
1405                     auto w = x.weak;    //weak ptr
1406 
1407                     RcPtr!long y = w.lock;
1408 
1409                     assert(x == y);
1410                     assert(x.useCount == 2);
1411                     assert(y.get == 123);
1412                 }
1413 
1414                 {
1415                     RcPtr!long x = RcPtr!long.make(123);
1416 
1417                     auto w = x.weak;    //weak ptr
1418 
1419                     assert(w.expired == false);
1420 
1421                     x = RcPtr!long.make(321);
1422 
1423                     assert(w.expired == true);
1424 
1425                     RcPtr!long y = w.lock;
1426 
1427                     assert(y == null);
1428                 }
1429                 --------------------
1430         */
1431         public SharedType lock()()scope
1432         if(isCopyConstructable!(typeof(this), SharedType)){
1433             return typeof(return)(this);
1434         }
1435 
1436 
1437 
1438         /**
1439             Equivalent to `useCount() == 0` (must be `RcPtr.WeakType`).
1440 
1441             Method exists only if `RcPtr` is `isWeak`
1442 
1443             Examples:
1444                 --------------------
1445                 {
1446                     RcPtr!long x = RcPtr!long.make(123);
1447 
1448                     auto wx = x.weak;   //weak pointer
1449 
1450                     assert(wx.expired == false);
1451 
1452                     x = null;
1453 
1454                     assert(wx.expired == true);
1455                 }
1456                 --------------------
1457         */
1458         public @property bool expired(this This)()scope const nothrow @safe @nogc{
1459             return (this.useCount == 0);
1460         }
1461 
1462 
1463 
1464         static if(!isWeak){
1465             /**
1466                 Operator *, same as method 'get'.
1467 
1468                 Examples:
1469                     --------------------
1470                     RcPtr!long x = RcPtr!long.make(123);
1471                     assert(*x == 123);
1472                     (*x = 321);
1473                     assert(*x == 321);
1474                     const y = x;
1475                     assert(*y == 321);
1476                     assert(*x == 321);
1477                     static assert(is(typeof(*y) == const long));
1478                     --------------------
1479             */
1480             public template opUnary(string op : "*")
1481             if(op == "*"){  //doc
1482                 alias opUnary = get;
1483             }
1484 
1485 
1486 
1487             /**
1488                 Get reference to managed object of `ElementType` or value if `ElementType` is reference type (class or interface) or dynamic array.
1489 
1490                 Examples:
1491                     --------------------
1492                     RcPtr!long x = RcPtr!long.make(123);
1493                     assert(x.get == 123);
1494                     x.get = 321;
1495                     assert(x.get == 321);
1496                     const y = x;
1497                     assert(y.get == 321);
1498                     assert(x.get == 321);
1499                     static assert(is(typeof(y.get) == const long));
1500                     --------------------
1501             */
1502             static if(referenceElementType){
1503                 public @property inout(ElementType) get()inout return pure nothrow @safe @nogc{
1504                     return this._element;
1505                 }
1506             }
1507             else static if(is(Unqual!ElementType == void)){
1508                 /// ditto
1509                 public @property inout(ElementType) get()inout scope pure nothrow @safe @nogc{
1510                 }
1511             }
1512             else{
1513                 /// ditto
1514                 public @property ref inout(ElementType) get()inout return pure nothrow @system @nogc{
1515                     return *cast(inout(ElementType)*)this._element;
1516                 }
1517             }
1518 
1519         }
1520 
1521 
1522 
1523         /**
1524             Get pointer to managed object of `ElementType` or reference if `ElementType` is reference type (class or interface) or dynamic array.
1525 
1526             If `this` is weak expired pointer then return null.
1527 
1528             Doesn't increment useCount, is inherently unsafe.
1529 
1530             Examples:
1531                 --------------------
1532                 {
1533                     RcPtr!long x = RcPtr!long.make(123);
1534                     assert(*x.element == 123);
1535 
1536                     x.get = 321;
1537                     assert(*x.element == 321);
1538 
1539                     const y = x;
1540                     assert(*y.element == 321);
1541                     assert(*x.element == 321);
1542 
1543                     static assert(is(typeof(y.element) == const(long)*));
1544                 }
1545 
1546                 {
1547                     auto x = RcPtr!(long[]).make(6, 42);
1548                     assert(x.element[0] == 42);
1549                     static assert(is(typeof(x.element) == long[]));
1550                 }
1551 
1552                 {
1553                     auto s = RcPtr!long.make(42);
1554                     const w = s.weak;
1555 
1556                     assert(*w.element == 42);
1557 
1558                     s = null;
1559                     assert(w.element is null);
1560                 }
1561 
1562                 {
1563                     auto s = RcPtr!long.make(42);
1564                     auto w = s.weak;
1565 
1566                     scope const p = w.element;
1567 
1568                     s = null;
1569                     assert(w.element is null);
1570 
1571                     assert(p !is null); //p is dangling pointer!
1572                 }
1573                 --------------------
1574         */
1575         public @property ElementReferenceTypeImpl!(GetElementType!This) element(this This)()return pure nothrow @system @nogc
1576         if(!is(This == shared)){
1577             static if(isWeak)
1578                 return (cast(const)this).expired
1579                     ? null
1580                     : this._element;
1581             else
1582                 return this._element;
1583         }
1584 
1585 
1586 
1587         /**
1588             Get pointer to managed object of `ElementType` or reference if `ElementType` is reference type (class or interface) or pointer to first dynamic array element.
1589 
1590             If `this` is weak expired pointer then return null.
1591 
1592             Doesn't increment useCount, is inherently unsafe.
1593 
1594             Examples:
1595                 --------------------
1596                 {
1597                     RcPtr!long x = RcPtr!long.make(123);
1598                     assert(*x.ptr == 123);
1599 
1600                     x.get = 321;
1601                     assert(*x.ptr == 321);
1602 
1603                     const y = x;
1604                     assert(*y.ptr == 321);
1605                     assert(*x.ptr == 321);
1606 
1607                     static assert(is(typeof(y.ptr) == const(long)*));
1608                 }
1609 
1610                 {
1611                     auto x = RcPtr!(long[]).make(6, 42);
1612                     assert(*x.ptr == 42);
1613                     static assert(is(typeof(x.ptr) == long*));
1614                 }
1615 
1616                 {
1617                     auto s = RcPtr!long.make(42);
1618                     const w = s.weak;
1619 
1620                     assert(*w.ptr == 42);
1621 
1622                     s = null;
1623                     assert(w.ptr is null);
1624                 }
1625 
1626                 {
1627                     auto s = RcPtr!long.make(42);
1628                     auto w = s.weak;
1629 
1630                     scope const p = w.ptr;
1631 
1632                     s = null;
1633                     assert(w.ptr is null);
1634 
1635                     assert(p !is null); //p is dangling pointer!
1636                 }
1637                 --------------------
1638         */
1639         public @property ElementPointerTypeImpl!(GetElementType!This) ptr(this This)()return pure nothrow @system @nogc
1640         if(!is(This == shared)){
1641             auto get_ptr(){
1642                 static if(isDynamicArray!ElementType)
1643                     return this._element.ptr;
1644                 else
1645                     return this._element;
1646             }
1647 
1648 
1649 
1650             static if(isWeak)
1651                 return (cast(const)this).expired
1652                     ? null
1653                     : get_ptr();
1654             else
1655                 return get_ptr();
1656         }
1657 
1658 
1659 
1660         /**
1661             Returns length of dynamic array (isDynamicArray!ElementType == true).
1662 
1663             Examples:
1664                 --------------------
1665                 auto x = RcPtr!(int[]).make(10, -1);
1666                 assert(x.length == 10);
1667                 assert(x.get.length == 10);
1668 
1669                 import std.algorithm : all;
1670                 assert(x.get.all!(i => i == -1));
1671                 --------------------
1672         */
1673         static if(isDynamicArray!ElementType)
1674         public @property size_t length()const scope pure nothrow @safe @nogc{
1675             return this._element.length;
1676         }
1677 
1678 
1679         /**
1680             Returns weak pointer (must have weak counter).
1681 
1682             Examples:
1683                 --------------------
1684                 RcPtr!long x = RcPtr!long.make(123);
1685                 assert(x.useCount == 1);
1686 
1687                 auto wx = x.weak;   //weak pointer
1688                 assert(wx.expired == false);
1689                 assert(wx.lock.get == 123);
1690                 assert(wx.useCount == 1);
1691 
1692                 x = null;
1693                 assert(wx.expired == true);
1694                 assert(wx.useCount == 0);
1695                 --------------------
1696         */
1697         public WeakType weak()()scope
1698         if(isCopyConstructable!(typeof(this), WeakType)){
1699             static if(hasWeakCounter){
1700                 return typeof(return)(this);
1701             }
1702         }
1703 
1704 
1705 
1706         /**
1707             Checks if `this` stores a non-null pointer, i.e. whether `this != null`.
1708 
1709             Examples:
1710                 --------------------
1711                 RcPtr!long x = RcPtr!long.make(123);
1712                 assert(cast(bool)x);    //explicit cast
1713                 assert(x);              //implicit cast
1714                 x = null;
1715                 assert(!cast(bool)x);   //explicit cast
1716                 assert(!x);             //implicit cast
1717                 --------------------
1718         */
1719         public bool opCast(To : bool)()const scope pure nothrow @safe @nogc
1720         if(is(To : bool)){ //docs
1721             return (this != null);
1722         }
1723 
1724 
1725 
1726         /**
1727             Support for quelifier cast.
1728         */
1729         public ref To opCast(To, this This)()return scope pure nothrow @nogc
1730         if(is(immutable To : immutable typeof(this))){
1731             static if(is(This : To)){
1732                 return *(()@trusted => cast(To*)&this )();
1733             }
1734             else{
1735                 return *(()@system => cast(To*)&this )();
1736             }
1737         }
1738 
1739 
1740 
1741         /**
1742             Cast `this` to different type `To` when `isRcPtr!To`.
1743 
1744             BUG: qualfied variable of struct with dtor cannot be inside other struct (generated dtor will use opCast to mutable before dtor call ). opCast is renamed to opCastImpl
1745 
1746             Examples:
1747                 --------------------
1748                 RcPtr!long x = RcPtr!long.make(123);
1749                 auto y = cast(RcPtr!(const long))x;
1750                 auto z = cast(const RcPtr!long)x;
1751                 auto u = cast(const RcPtr!(const long))x;
1752                 assert(x.useCount == 4);
1753                 --------------------
1754         */
1755         public To opCastImpl(To, this This)()scope
1756         if(isRcPtr!To && !is(This == shared)){
1757             return To(this);
1758         }
1759 
1760 
1761         /**
1762             Operator == and != .
1763             Compare pointers.
1764 
1765             Examples:
1766                 --------------------
1767                 {
1768                     RcPtr!long x = RcPtr!long.make(0);
1769                     assert(x != null);
1770                     x = null;
1771                     assert(x == null);
1772                 }
1773 
1774                 {
1775                     RcPtr!long x = RcPtr!long.make(123);
1776                     RcPtr!long y = RcPtr!long.make(123);
1777                     assert(x == x);
1778                     assert(y == y);
1779                     assert(x != y);
1780                 }
1781 
1782                 {
1783                     RcPtr!long x;
1784                     RcPtr!(const long) y;
1785                     assert(x == x);
1786                     assert(y == y);
1787                     assert(x == y);
1788                 }
1789 
1790                 {
1791                     RcPtr!long x = RcPtr!long.make(123);
1792                     RcPtr!long y = RcPtr!long.make(123);
1793                     assert(x == x.element);
1794                     assert(y.element == y);
1795                     assert(x != y.element);
1796                 }
1797                 --------------------
1798         */
1799         public bool opEquals(typeof(null) nil)const @safe scope pure nothrow @nogc{
1800             static if(isDynamicArray!ElementType)
1801                 return (this._element.length == 0);
1802             else
1803                 return (this._element is null);
1804         }
1805 
1806         /// ditto
1807         public bool opEquals(Rhs)(scope auto ref const Rhs rhs)const @safe scope pure nothrow @nogc
1808         if(isRcPtr!Rhs && !is(Rhs == shared)){
1809             return this.opEquals(rhs._element);
1810         }
1811 
1812         /// ditto
1813         public bool opEquals(Elm)(scope const Elm elm)const @safe scope pure nothrow @nogc
1814         if(is(Elm : GetElementReferenceType!(typeof(this)))){
1815             static if(isDynamicArray!ElementType){
1816                 static assert(isDynamicArray!Elm);
1817 
1818                 if(this._element.length != elm.length)
1819                     return false;
1820 
1821                 if(this._element.ptr is elm.ptr)
1822                     return true;
1823 
1824                 return (this._element.length == 0);
1825             }
1826             else{
1827                 return (this._element is elm);
1828             }
1829         }
1830 
1831 
1832 
1833         /**
1834             Operators <, <=, >, >= for `RcPtr`.
1835 
1836             Compare address of payload.
1837 
1838             Examples:
1839                 --------------------
1840                 {
1841                     const a = RcPtr!long.make(42);
1842                     const b = RcPtr!long.make(123);
1843                     const n = RcPtr!long.init;
1844 
1845                     assert(a <= a);
1846                     assert(a >= a);
1847 
1848                     assert((a < b) == !(a >= b));
1849                     assert((a > b) == !(a <= b));
1850 
1851                     assert(a > n);
1852                     assert(a > null);
1853 
1854                     assert(n < a);
1855                     assert(null < a);
1856                 }
1857 
1858                 {
1859                     const a = RcPtr!long.make(42);
1860                     const b = RcPtr!long.make(123);
1861 
1862                     assert(a <= a.element);
1863                     assert(a.element >= a);
1864 
1865                     assert((a < b.element) == !(a.element >= b));
1866                     assert((a > b.element) == !(a.element <= b));
1867                 }
1868                 --------------------
1869         */
1870         public sizediff_t opCmp(typeof(null) nil)const @trusted scope pure nothrow @nogc{
1871             static if(isDynamicArray!ElementType){
1872                 return this._element.length;
1873             }
1874             else{
1875                 return (cast(const void*)this._element) - (cast(const void*)null);
1876             }
1877 
1878         }
1879 
1880         /// ditto
1881         public sizediff_t opCmp(Elm)(scope const Elm elm)const @trusted scope pure nothrow @nogc
1882         if(is(Elm : GetElementReferenceType!(typeof(this)))){
1883             static if(isDynamicArray!ElementType){
1884                 const void* lhs = cast(const void*)(this._element.ptr + this._element.length);
1885                 const void* rhs = cast(const void*)(elm.ptr + elm.length);
1886 
1887                 return lhs - rhs;
1888             }
1889             else{
1890                 return (cast(const void*)this._element) - (cast(const void*)elm);
1891             }
1892         }
1893 
1894         /// ditto
1895         public sizediff_t opCmp(Rhs)(scope auto ref const Rhs rhs)const @trusted scope pure nothrow @nogc
1896         if(isRcPtr!Rhs && !is(Rhs == shared)){
1897             return this.opCmp(rhs._element);
1898         }
1899 
1900 
1901 
1902         /**
1903             Generate hash
1904 
1905             Return:
1906                 Address of payload as `size_t`
1907 
1908             Examples:
1909                 --------------------
1910                 {
1911                     RcPtr!long x = RcPtr!long.make(123);
1912                     RcPtr!long y = RcPtr!long.make(123);
1913                     assert(x.toHash == x.toHash);
1914                     assert(y.toHash == y.toHash);
1915                     assert(x.toHash != y.toHash);
1916                     RcPtr!(const long) z = x;
1917                     assert(x.toHash == z.toHash);
1918                 }
1919                 {
1920                     RcPtr!long x;
1921                     RcPtr!(const long) y;
1922                     assert(x.toHash == x.toHash);
1923                     assert(y.toHash == y.toHash);
1924                     assert(x.toHash == y.toHash);
1925                 }
1926                 --------------------
1927         */
1928         public @property size_t toHash()@trusted scope const pure nothrow @nogc {
1929             static if(isDynamicArray!ElementType)
1930                 return cast(size_t)cast(void*)(this._element.ptr + this._element.length);
1931             else
1932                 return cast(size_t)cast(void*)this._element;
1933         }
1934 
1935 
1936 
1937         package ElementReferenceType _element;
1938 
1939         private void _release()scope{
1940             if(false){
1941                 DestructorType dt;
1942                 dt(null);
1943             }
1944 
1945             if(this._element !is null)
1946                 this._control.release!isWeak;
1947         }
1948 
1949         package GetControlType!This* _control(this This)()pure nothrow @trusted @nogc
1950         in(this._element !is null){
1951             static if(isDynamicArray!ElementType){
1952                 return cast(typeof(return))((cast(void*)this._element.ptr) - ControlType.sizeof);
1953             }
1954             else static if(is(ElementType == interface)){
1955                 static assert(__traits(getLinkage, ElementType) == "D");
1956                 return cast(typeof(return))((cast(void*)cast(Object)cast(Unqual!ElementType)this._element) - ControlType.sizeof);
1957             }
1958             else{
1959                 return cast(typeof(return))((cast(void*)this._element) - ControlType.sizeof);
1960             }
1961         }
1962 
1963         private void _reset()scope pure nothrow @system @nogc{
1964             this._set_element(null);
1965         }
1966 
1967         package void _const_reset()scope const pure nothrow @system @nogc{
1968             auto self = cast(Unqual!(typeof(this))*)&this;
1969 
1970             self._reset();
1971         }
1972 
1973         private void _set_element(ElementReferenceType e)pure nothrow @system @nogc{
1974             (*cast(Unqual!ElementReferenceType*)&this._element) = cast(Unqual!ElementReferenceType)e;
1975         }
1976 
1977         private void _const_set_element(ElementReferenceType e)const pure nothrow @system @nogc{
1978             auto self = cast(Unqual!(typeof(this))*)&this;
1979 
1980             static if(isMutable!ElementReferenceType)
1981                 self._element = e;
1982             else
1983                 (*cast(Unqual!ElementReferenceType*)&self._element) = cast(Unqual!ElementReferenceType)e;
1984         }
1985 
1986         package auto _move()@trusted{
1987             auto e = this._element;
1988             this._const_reset();
1989 
1990             return typeof(this)(e, Forward.init);
1991         }
1992 
1993         private alias MakeEmplace(AllocatorType, bool supportGC) = .MakeEmplace!(
1994             _Type,
1995             _DestructorType,
1996             _ControlType,
1997             AllocatorType,
1998             supportGC
1999         );
2000 
2001         private alias MakeDynamicArray(AllocatorType, bool supportGC) = .MakeDynamicArray!(
2002             _Type,
2003             _DestructorType,
2004             _ControlType,
2005             AllocatorType,
2006             supportGC
2007         );
2008 
2009         package alias SmartPtr = .SmartPtr;
2010 
2011         /**/
2012         package alias ChangeElementType(T) = RcPtr!(
2013             CopyTypeQualifiers!(ElementType, T),
2014             DestructorType,
2015             ControlType,
2016             isWeak
2017         );
2018     }
2019 
2020 }
2021 
2022 
2023 
2024 /// Alias to `RcPtr` with different order of template parameters
2025 public template RcPtr(
2026     _Type,
2027     _ControlType,
2028     _DestructorType = DestructorType!_Type
2029 )
2030 if(isControlBlock!_ControlType && isDestructorType!_DestructorType){
2031     alias RcPtr = .RcPtr!(_Type, _DestructorType, _ControlType, false);
2032 }
2033 
2034 ///
2035 unittest{
2036     static class Foo{
2037         int i;
2038 
2039         this(int i)pure nothrow @safe @nogc{
2040             this.i = i;
2041         }
2042     }
2043 
2044     static class Bar : Foo{
2045         double d;
2046 
2047         this(int i, double d)pure nothrow @safe @nogc{
2048             super(i);
2049             this.d = d;
2050         }
2051     }
2052 
2053     static class Zee : Bar{
2054         bool b;
2055 
2056         this(int i, double d, bool b)pure nothrow @safe @nogc{
2057             super(i, d);
2058             this.b = b;
2059         }
2060 
2061         ~this()nothrow @system{
2062         }
2063     }
2064 
2065     ///simple:
2066     {
2067         RcPtr!long a = RcPtr!long.make(42);
2068         assert(a.useCount == 1);
2069 
2070         RcPtr!(const long) b = a;
2071         assert(a.useCount == 2);
2072 
2073         RcPtr!long.WeakType w = a.weak; //or WeakRcPtr!long
2074         assert(a.useCount == 2);
2075         assert(a.weakCount == 1);
2076 
2077         RcPtr!long c = w.lock;
2078         assert(a.useCount == 3);
2079         assert(a.weakCount == 1);
2080 
2081         assert(*c == 42);
2082         assert(c.get == 42);
2083     }
2084 
2085     ///polymorphism and aliasing:
2086     {
2087         ///create RcPtr
2088         RcPtr!Foo foo = RcPtr!Bar.make(42, 3.14);
2089         RcPtr!Zee zee = RcPtr!Zee.make(42, 3.14, false);
2090 
2091         ///dynamic cast:
2092         RcPtr!Bar bar = dynCast!Bar(foo);
2093         assert(bar != null);
2094         assert(foo.useCount == 2);
2095 
2096         ///this doesnt work because Foo destructor attributes are more restrictive then Zee's:
2097         //RcPtr!Foo x = zee;
2098 
2099         ///this does work:
2100         RcPtr!(Foo, DestructorType!(Foo, Zee)) x = zee;
2101         assert(zee.useCount == 2);
2102     }
2103 
2104 
2105     ///multi threading:
2106     {
2107         ///create RcPtr with atomic ref counting
2108         RcPtr!(shared Foo) foo = RcPtr!(shared Bar).make(42, 3.14);
2109 
2110         ///this doesnt work:
2111         //foo.get.i += 1;
2112 
2113         import core.atomic : atomicFetchAdd;
2114         atomicFetchAdd(foo.get.i, 1);
2115         assert(foo.get.i == 43);
2116 
2117 
2118         ///creating `shared(RcPtr)`:
2119         shared RcPtr!(shared Bar) bar = share(dynCast!Bar(foo));
2120 
2121         ///`shared(RcPtr)` is lock free (except `load` and `useCount`/`weakCount`).
2122         static assert(typeof(bar).isLockFree == true);
2123 
2124         ///multi thread operations (`load`, `store`, `exchange` and `compareExchange`):
2125         RcPtr!(shared Bar) bar2 = bar.load();
2126         assert(bar2 != null);
2127         assert(bar2.useCount == 3);
2128 
2129         RcPtr!(shared Bar) bar3 = bar.exchange(null);
2130         assert(bar3 != null);
2131         assert(bar3.useCount == 3);
2132     }
2133 
2134     ///dynamic array:
2135     {
2136         import std.algorithm : all, equal;
2137 
2138         RcPtr!(long[]) a = RcPtr!(long[]).make(10, -1);
2139         assert(a.length == 10);
2140         assert(a.get.length == 10);
2141         assert(a.get.all!(x => x == -1));
2142 
2143         for(int i = 0; i < a.length; ++i){
2144             a.get[i] = i;
2145         }
2146         assert(a.get[] == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
2147     }
2148 }
2149 
2150 //old:
2151 pure nothrow @nogc unittest{
2152 
2153     static class Foo{
2154         int i;
2155 
2156         this(int i)pure nothrow @safe @nogc{
2157             this.i = i;
2158         }
2159     }
2160 
2161     static class Bar : Foo{
2162         double d;
2163 
2164         this(int i, double d)pure nothrow @safe @nogc{
2165             super(i);
2166             this.d = d;
2167         }
2168     }
2169 
2170     //implicit qualifier cast
2171     {
2172         RcPtr!(const Foo) foo =  RcPtr!Foo.make(42);
2173         assert(foo.get.i == 42);
2174         assert(foo.useCount == 1);
2175 
2176         const RcPtr!Foo foo2 = foo;
2177         assert(foo2.get.i == 42);
2178         assert(foo.useCount == 2);
2179 
2180     }
2181 
2182     //polymorphic classes:
2183     {
2184         RcPtr!Foo foo = RcPtr!Bar.make(42, 3.14);
2185         assert(foo != null);
2186         assert(foo.useCount == 1);
2187         assert(foo.get.i == 42);
2188 
2189         //dynamic cast:
2190         {
2191             RcPtr!Bar bar = dynCast!Bar(foo);
2192             assert(foo.useCount == 2);
2193 
2194             assert(bar.get.i == 42);
2195             assert(bar.get.d == 3.14);
2196         }
2197 
2198     }
2199 
2200     //weak references:
2201     {
2202 
2203         auto x = RcPtr!double.make(3.14);
2204         assert(x.useCount == 1);
2205         assert(x.weakCount == 0);
2206 
2207         auto w = x.weak();  //weak pointer
2208         assert(x.useCount == 1);
2209         assert(x.weakCount == 1);
2210         assert(*w.lock == 3.14);
2211 
2212         RcPtr!double.WeakType w2 = x;
2213         assert(x.useCount == 1);
2214         assert(x.weakCount == 2);
2215 
2216         assert(w2.expired == false);
2217         x = null;
2218         assert(w2.expired == true);
2219     }
2220 
2221     //dynamic array
2222     {
2223         import std.algorithm : all;
2224 
2225         {
2226             auto arr = RcPtr!(long[]).make(10, -1);
2227 
2228             assert(arr.length == 10);
2229             assert(arr.get.all!(x => x == -1));
2230         }
2231 
2232         {
2233             auto arr = RcPtr!(long[]).make(8);
2234             assert(arr.length == 8);
2235             assert(arr.get.all!(x => x == long.init));
2236         }
2237     }
2238 
2239     //static array
2240     {
2241         import std.algorithm : all;
2242 
2243         {
2244             auto arr = RcPtr!(long[4]).make(-1);
2245             assert(arr.get[].all!(x => x == -1));
2246 
2247         }
2248 
2249         {
2250             long[4] tmp = [0, 1, 2, 3];
2251             auto arr = RcPtr!(long[4]).make(tmp);
2252             assert(arr.get[] == tmp[]);
2253         }
2254     }
2255 
2256 }
2257 
2258 ///
2259 pure nothrow @safe @nogc unittest{
2260     //make RcPtr object
2261     static struct Foo{
2262         int i;
2263 
2264         this(int i)pure nothrow @safe @nogc{
2265             this.i = i;
2266         }
2267     }
2268 
2269     {
2270         auto foo = RcPtr!Foo.make(42);
2271         auto foo2 = RcPtr!Foo.make!Mallocator(42);  //explicit stateless allocator
2272     }
2273 
2274     {
2275         auto arr = RcPtr!(long[]).make(10); //dynamic array with length 10
2276         assert(arr.length == 10);
2277     }
2278 }
2279 
2280 ///
2281 nothrow unittest{
2282     //alloc RcPtr object
2283     import std.experimental.allocator : make, dispose, allocatorObject;
2284 
2285     auto allocator = allocatorObject(Mallocator.instance);
2286 
2287     {
2288         auto x = RcPtr!(long).alloc(allocator, 42);
2289     }
2290 
2291     {
2292         import btl.internal.traits;
2293         static assert(isMoveConstructableElement!(typeof(allocator)));
2294         auto arr = RcPtr!(long[]).alloc(allocator, 10); //dynamic array with length 10
2295         assert(arr.length == 10);
2296     }
2297 
2298 }
2299 
2300 
2301 //make:
2302 pure nothrow @safe @nogc unittest{
2303     import std.experimental.allocator : allocatorObject;
2304 
2305     enum bool supportGC = true;
2306 
2307     //
2308     {
2309         auto s = RcPtr!long.make(42);
2310     }
2311 
2312     {
2313         auto s = RcPtr!long.make!(DefaultAllocator, supportGC)(42);
2314     }
2315 
2316     {
2317         auto s = RcPtr!(long, shared(SharedControlBlock)).make!(DefaultAllocator, supportGC)(42);
2318     }
2319 
2320 
2321     // dynamic array:
2322     {
2323         auto s = RcPtr!(long[]).make(10, 42);
2324         assert(s.length == 10);
2325     }
2326 
2327     {
2328         auto s = RcPtr!(long[]).make!(DefaultAllocator, supportGC)(10, 42);
2329         assert(s.length == 10);
2330     }
2331 
2332     {
2333         auto s = RcPtr!(long[], shared(SharedControlBlock)).make!(DefaultAllocator, supportGC)(10, 42);
2334         assert(s.length == 10);
2335     }
2336 }
2337 
2338 //alloc:
2339 nothrow unittest{
2340     import std.experimental.allocator : allocatorObject;
2341 
2342     auto a = allocatorObject(Mallocator.instance);
2343     enum bool supportGC = true;
2344 
2345     //
2346     {
2347         auto s = RcPtr!long.alloc(a, 42);
2348     }
2349 
2350     {
2351         auto s = RcPtr!long.alloc!supportGC(a, 42);
2352     }
2353 
2354     {
2355         auto s = RcPtr!(long, shared(SharedControlBlock)).alloc!supportGC(a, 42);
2356     }
2357 
2358 
2359     // dynamic array:
2360     {
2361         auto s = RcPtr!(long[]).alloc(a, 10, 42);
2362         assert(s.length == 10);
2363     }
2364 
2365     {
2366         auto s = RcPtr!(long[]).alloc!supportGC(a, 10, 42);
2367         assert(s.length == 10);
2368     }
2369 
2370     {
2371         auto s = RcPtr!(long[], shared(SharedControlBlock)).alloc!supportGC(a, 10, 42);
2372         assert(s.length == 10);
2373     }
2374 }
2375 
2376 
2377 
2378 /**
2379     Dynamic cast for shared pointers if `ElementType` is class with D linkage.
2380 
2381     Creates a new instance of `RcPtr` whose stored pointer is obtained from `ptr`'s stored pointer using a dynaic cast expression.
2382 
2383     If `ptr` is null or dynamic cast fail then result `RcPtr` is null.
2384     Otherwise, the new `RcPtr` will share ownership with the initial value of `ptr`.
2385 */
2386 public UnqualSmartPtr!Ptr.ChangeElementType!T dynCast(T, Ptr)(scope auto ref Ptr ptr)
2387 if(    isRcPtr!Ptr && !is(Ptr == shared) && !Ptr.isWeak
2388     && isClassOrInterface!T && __traits(getLinkage, T) == "D"
2389     && isClassOrInterface!(Ptr.ElementType) && __traits(getLinkage, Ptr.ElementType) == "D"
2390 ){
2391     static if(isRef!ptr){
2392         if(auto element = dynCastElement!T(ptr._element)){
2393             return typeof(return)(ptr._control, element);
2394         }
2395 
2396         return typeof(return).init;
2397     }
2398     else{
2399         return dynCastMove!T(ptr);
2400     }
2401 }
2402 
2403 /// ditto
2404 public UnqualSmartPtr!Ptr.ChangeElementType!T dynCastMove(T, Ptr)(scope auto ref Ptr ptr)
2405 if(    isRcPtr!Ptr && !is(Ptr == shared) && !Ptr.isWeak
2406     && isClassOrInterface!T && __traits(getLinkage, T) == "D"
2407     && isClassOrInterface!(Ptr.ElementType) && __traits(getLinkage, Ptr.ElementType) == "D"
2408 ){
2409     if(auto element = dynCastElement!T(ptr._element)){
2410         ()@trusted{
2411             ptr._const_reset();
2412         }();
2413         return typeof(return)(element, Forward.init);
2414     }
2415 
2416     return typeof(return).init;
2417 }
2418 
2419 
2420 ///
2421 unittest{
2422     static class Foo{
2423         int i;
2424 
2425         this(int i)pure nothrow @safe @nogc{
2426             this.i = i;
2427         }
2428     }
2429 
2430     static class Bar : Foo{
2431         double d;
2432 
2433         this(int i, double d)pure nothrow @safe @nogc{
2434             super(i);
2435             this.d = d;
2436         }
2437     }
2438 
2439     static class Zee{
2440     }
2441 
2442     {
2443         RcPtr!(const Foo) foo = RcPtr!Bar.make(42, 3.14);
2444         assert(foo.get.i == 42);
2445 
2446         auto bar = dynCast!Bar(foo);
2447         assert(bar != null);
2448         assert(bar.get.d == 3.14);
2449         static assert(is(typeof(bar) == RcPtr!(const Bar)));
2450 
2451         auto zee = dynCast!Zee(foo);
2452         assert(zee == null);
2453         static assert(is(typeof(zee) == RcPtr!(const Zee)));
2454     }
2455 
2456     {
2457         RcPtr!(const Foo) foo = RcPtr!Bar.make(42, 3.14);
2458         assert(foo.get.i == 42);
2459 
2460         import core.lifetime : move;
2461         auto bar = dynCast!Bar(foo.move);
2462         assert(bar != null);
2463         assert(bar.get.d == 3.14);
2464         static assert(is(typeof(bar) == RcPtr!(const Bar)));
2465     }
2466 
2467     {
2468         RcPtr!(const Foo) foo = RcPtr!Bar.make(42, 3.14);
2469         assert(foo.get.i == 42);
2470 
2471         auto bar = dynCastMove!Bar(foo);
2472         assert(foo == null);
2473         assert(bar != null);
2474         assert(bar.get.d == 3.14);
2475         static assert(is(typeof(bar) == RcPtr!(const Bar)));
2476     }
2477 }
2478 
2479 
2480 
2481 
2482 
2483 
2484 /**
2485     Return `shared RcPtr` pointing to same managed object like parameter `ptr`.
2486 
2487     Type of parameter `ptr` must be `RcPtr` with `shared(ControlType)` and `shared`/`immutable` `ElementType` .
2488 */
2489 public shared(Ptr) share(Ptr)(scope auto ref Ptr ptr)
2490 if(isRcPtr!Ptr){
2491     import core.lifetime : forward;
2492     static if(is(Ptr == shared)){
2493         return forward!ptr;
2494     }
2495     else{
2496         static assert(is(GetControlType!Ptr == shared) || is(GetControlType!Ptr == immutable),
2497             "`RcPtr` has not shared ref counter `ControlType`."
2498         );
2499 
2500         static assert(is(GetElementType!Ptr == shared) || is(GetElementType!Ptr == immutable),
2501             "`RcPtr` has not shared/immutable `ElementType`."
2502         );
2503 
2504         return typeof(return)(forward!ptr, Forward.init);
2505     }
2506 }
2507 
2508 ///
2509 nothrow @nogc unittest{
2510     {
2511         auto x = RcPtr!(shared long).make(123);
2512         assert(x.useCount == 1);
2513 
2514         shared s1 = share(x);
2515         assert(x.useCount == 2);
2516 
2517 
2518         import core.lifetime : move;
2519         shared s2 = share(x.move);
2520         assert(x == null);
2521         assert(s2.useCount == 2);
2522         assert(s2.load.get == 123);
2523 
2524     }
2525 
2526     {
2527         auto x = RcPtr!(long).make(123);
2528         assert(x.useCount == 1);
2529 
2530         ///error `shared RcPtr` need shared `ControlType` and shared `ElementType`.
2531         //shared s1 = share(x);
2532 
2533     }
2534 
2535 }
2536 
2537 
2538 
2539 /**
2540     Return `RcPtr` pointing to first element of dynamic array managed by rc pointer `ptr`.
2541 */
2542 public auto first(Ptr)(scope ref Ptr ptr)@trusted
2543 if(isRcPtr!Ptr && is(Ptr.ElementType : T[], T)){
2544     import std.traits : isDynamicArray, isStaticArray;
2545     import std.range : ElementEncodingType;
2546 
2547     alias Result = UnqualSmartPtr!Ptr.ChangeElementType!(
2548         ElementEncodingType!(Ptr.ElementType)
2549     );
2550 
2551     if(ptr == null)
2552         return Result.init;
2553 
2554     static if(isDynamicArray!(Ptr.ElementType) || isStaticArray!(Ptr.ElementType)){
2555         return Result(ptr._control, ptr._element.ptr);
2556     }
2557     else static assert(0, "no impl");
2558 }
2559 
2560 /// ditto
2561 public auto first(Ptr)(scope Ptr ptr)@trusted
2562 if(isRcPtr!Ptr && is(Ptr.ElementType : T[], T)){
2563     import std.traits : isDynamicArray, isStaticArray;
2564     import std.range : ElementEncodingType;
2565 
2566     alias Result = UnqualSmartPtr!Ptr.ChangeElementType!(
2567         ElementEncodingType!(Ptr.ElementType)
2568     );
2569 
2570     if(ptr == null)
2571         return Result.init;
2572 
2573     static if(isDynamicArray!(Ptr.ElementType) || isStaticArray!(Ptr.ElementType)){
2574         auto ptr_element = ptr._element.ptr;
2575         ptr._const_reset();
2576         return Result(ptr_element, Forward.init);
2577     }
2578     else static assert(0, "no impl");
2579 }
2580 
2581 ///
2582 pure nothrow @nogc unittest{
2583     //copy
2584     {
2585         auto x = RcPtr!(long[]).make(10, -1);
2586         assert(x.length == 10);
2587 
2588         auto y = first(x);
2589         static assert(is(typeof(y) == RcPtr!long));
2590         assert(*y == -1);
2591         assert(x.useCount == 2);
2592     }
2593 
2594     {
2595         auto x = RcPtr!(long[10]).make(-1);
2596         assert(x.get.length == 10);
2597 
2598         auto y = first(x);
2599         static assert(is(typeof(y) == RcPtr!long));
2600         assert(*y == -1);
2601         assert(x.useCount == 2);
2602     }
2603 
2604     //move
2605     import core.lifetime : move;
2606     {
2607         auto x = RcPtr!(long[]).make(10, -1);
2608         assert(x.length == 10);
2609 
2610         auto y = first(x.move);
2611         static assert(is(typeof(y) == RcPtr!long));
2612         assert(*y == -1);
2613     }
2614 
2615     {
2616         auto x = RcPtr!(long[10]).make(-1);
2617         assert(x.get.length == 10);
2618 
2619         auto y = first(x.move);
2620         static assert(is(typeof(y) == RcPtr!long));
2621         assert(*y == -1);
2622     }
2623 }
2624 
2625 
2626 
2627 //local traits:
2628 private{
2629 
2630     //Constructable:
2631     template isMoveConstructable(From, To){
2632         import std.traits : Unqual, CopyTypeQualifiers;
2633 
2634         static if(is(Unqual!(From.ElementType) == Unqual!(To.ElementType)))
2635             enum bool overlapable = true;
2636 
2637         else static if(isClassOrInterface!(From.ElementType) && isClassOrInterface!(To.ElementType))
2638             enum bool overlapable = true
2639                 && (__traits(getLinkage, From.ElementType) == "D")
2640                 && (__traits(getLinkage, To.ElementType) == "D");
2641         else
2642             enum bool overlapable = false;
2643 
2644 
2645         enum bool isMoveConstructable = true
2646             && overlapable    //isOverlapable!(From.ElementType, To.ElementType) //&& is(Unqual!(From.ElementType) == Unqual!(To.ElementType))
2647             && is(GetElementReferenceType!From : GetElementReferenceType!To)
2648             && is(From.DestructorType : To.DestructorType)
2649             && is(GetControlType!From* : GetControlType!To*);
2650     }
2651     template isCopyConstructable(From, To){
2652         import std.traits : isMutable;
2653 
2654         enum bool isCopyConstructable = true
2655             && isMoveConstructable!(From, To)
2656             && isMutable!From
2657             && isMutable!(From.ControlType);
2658     }
2659     template isConstructable(alias from, To){
2660         enum bool isConstructable = isRef!from
2661             ? isCopyConstructable!(typeof(from), To)
2662             : isMoveConstructable!(typeof(from), To);
2663     }
2664 
2665     //Assignable:
2666     template isMoveAssignable(From, To){
2667         import std.traits : isMutable;
2668 
2669         enum bool isMoveAssignable = true
2670             && isMoveConstructable!(From, To)
2671             && !weakLock!(From, To)
2672             && isMutable!To;
2673     }
2674     template isCopyAssignable(From, To){
2675         import std.traits : isMutable;
2676 
2677         enum bool isCopyAssignable = true
2678             && isCopyConstructable!(From, To)
2679             && !weakLock!(From, To)
2680             && isMutable!To;
2681     }
2682     template isAssignable(alias from, To){
2683         enum bool isAssignable = isRef!from
2684             ? isCopyAssignable!(typeof(from), To)
2685             : isMoveAssignable!(typeof(from), To);
2686     }
2687 }
2688 
2689 
2690 version(unittest){
2691     import btl.internal.test_allocator;
2692 
2693     //copy ctor
2694     pure nothrow @nogc unittest{
2695 
2696 
2697         static struct Test{}
2698 
2699         import std.meta : AliasSeq;
2700         //alias Test = long;
2701         static foreach(alias ControlType; AliasSeq!(SharedControlBlock, shared SharedControlBlock)){{
2702             alias SPtr(T) = RcPtr!(T, DestructorType!T, ControlType);
2703 
2704             //mutable:
2705             {
2706                 alias Ptr = SPtr!(Test);
2707                 Ptr ptr;
2708                 static assert(__traits(compiles, Ptr(ptr)));
2709                 static assert(__traits(compiles, const(Ptr)(ptr)));
2710                 static assert(!__traits(compiles, immutable(Ptr)(ptr)));
2711                 static assert(!__traits(compiles, shared(Ptr)(ptr)));
2712                 static assert(!__traits(compiles, const(shared(Ptr))(ptr)));
2713             }
2714 
2715             //const:
2716             {
2717                 alias Ptr = SPtr!(const Test);
2718                 Ptr ptr;
2719                 static assert(__traits(compiles, Ptr(ptr)));
2720                 static assert(__traits(compiles, const(Ptr)(ptr)));
2721                 static assert(!__traits(compiles, immutable(Ptr)(ptr)));
2722                 static assert(!__traits(compiles, shared(Ptr)(ptr)));
2723                 static assert(!__traits(compiles, const(shared(Ptr))(ptr)));
2724             }
2725 
2726             //immutable:
2727             {
2728                 alias Ptr = SPtr!(immutable Test);
2729                 Ptr ptr;
2730                 static assert(__traits(compiles, Ptr(ptr)));
2731                 static assert(__traits(compiles, const(Ptr)(ptr)));
2732                 static assert(!__traits(compiles, immutable(Ptr)(ptr)));
2733                 static assert(__traits(compiles, shared(Ptr)(ptr)) == is(ControlType == shared));
2734                 static assert(__traits(compiles, const(shared(Ptr))(ptr)) == is(ControlType == shared));
2735             }
2736 
2737 
2738             //shared:
2739             {
2740                 alias Ptr = SPtr!(shared Test);
2741                 Ptr ptr;
2742                 static assert(__traits(compiles, Ptr(ptr)));
2743                 static assert(__traits(compiles, const(Ptr)(ptr)));
2744                 static assert(!__traits(compiles, immutable(Ptr)(ptr)));
2745                 static assert(__traits(compiles, shared(Ptr)(ptr)) == is(ControlType == shared));
2746                 static assert(__traits(compiles, const(shared(Ptr))(ptr)) == is(ControlType == shared));
2747             }
2748 
2749 
2750             //const shared:
2751             {
2752                 alias Ptr = SPtr!(const shared Test);
2753                 Ptr ptr;
2754                 static assert(__traits(compiles, Ptr(ptr)));
2755                 static assert(__traits(compiles, const(Ptr)(ptr)));
2756                 static assert(!__traits(compiles, immutable(Ptr)(ptr)));
2757                 static assert(__traits(compiles, shared(Ptr)(ptr)) == is(ControlType == shared));
2758                 static assert(__traits(compiles, const(shared(Ptr))(ptr)) == is(ControlType == shared));
2759             }
2760 
2761             static foreach(alias T; AliasSeq!(
2762                 Test,
2763                 const Test,
2764                 shared Test,
2765                 const shared Test,
2766                 immutable Test,
2767             )){{
2768                 alias Ptr = SPtr!T;
2769 
2770                 const(Ptr) cptr;
2771                 static assert(!__traits(compiles, Ptr(cptr)));
2772                 static assert(!__traits(compiles, const(Ptr)(cptr)));
2773                 static assert(!__traits(compiles, immutable(Ptr)(cptr)));
2774                 static assert(!__traits(compiles, shared(Ptr)(cptr)));
2775                 static assert(!__traits(compiles, const(shared(Ptr))(cptr)));
2776 
2777                 immutable(Ptr) iptr;
2778                 static assert(!__traits(compiles, Ptr(iptr)));
2779                 static assert(!__traits(compiles, const(Ptr)(iptr)));
2780                 static assert(!__traits(compiles, immutable(Ptr)(iptr)));
2781                 static assert(!__traits(compiles, shared(Ptr)(iptr)));
2782                 static assert(!__traits(compiles, const(shared(Ptr))(iptr)));
2783 
2784                 shared(Ptr) sptr;
2785                 static assert(!__traits(compiles, Ptr(sptr)));
2786                 static assert(!__traits(compiles, const(Ptr)(sptr)));
2787                 static assert(!__traits(compiles, immutable(Ptr)(sptr)));
2788                 static assert(!__traits(compiles, shared(Ptr)(sptr)));          //need load
2789                 static assert(!__traits(compiles, const shared Ptr(sptr)));     //need load
2790 
2791                 shared(const(Ptr)) scptr;
2792                 static assert(!__traits(compiles, Ptr(scptr)));
2793                 static assert(!__traits(compiles, const(Ptr)(scptr)));
2794                 static assert(!__traits(compiles, immutable(Ptr)(scptr)));
2795                 static assert(!__traits(compiles, shared(Ptr)(scptr)));         //need load
2796                 static assert(!__traits(compiles, const(shared(Ptr))(scptr)));  //need load
2797 
2798             }}
2799 
2800         }}
2801     }
2802 
2803     //this(typeof(null))
2804     pure nothrow @safe @nogc unittest{
2805         RcPtr!long x = null;
2806 
2807         assert(x == null);
2808         assert(x == RcPtr!long.init);
2809 
2810     }
2811 
2812 
2813     //opAssign(RcPtr)
2814     pure nothrow @nogc unittest{
2815 
2816         {
2817             RcPtr!long px1 = RcPtr!long.make(1);
2818             RcPtr!long px2 = RcPtr!long.make(2);
2819 
2820             assert(px2.useCount == 1);
2821             px1 = px2;
2822             assert(px1.get == 2);
2823             assert(px2.useCount == 2);
2824         }
2825 
2826 
2827 
2828         {
2829             RcPtr!long px = RcPtr!long.make(1);
2830             RcPtr!(const long) pcx = RcPtr!long.make(2);
2831 
2832             assert(px.useCount == 1);
2833             pcx = px;
2834             assert(pcx.get == 1);
2835             assert(pcx.useCount == 2);
2836 
2837         }
2838 
2839 
2840         /+{
2841             const RcPtr!long cpx = RcPtr!long.make(1);
2842             RcPtr!(const long) pcx = RcPtr!long.make(2);
2843 
2844             assert(pcx.useCount == 1);
2845             pcx = cpx;
2846             assert(pcx.get == 1);
2847             assert(pcx.useCount == 2);
2848 
2849         }+/
2850 
2851         {
2852             RcPtr!(immutable long) pix = RcPtr!(immutable long).make(123);
2853             RcPtr!(const long) pcx = RcPtr!long.make(2);
2854 
2855             assert(pix.useCount == 1);
2856             pcx = pix;
2857             assert(pcx.get == 123);
2858             assert(pcx.useCount == 2);
2859 
2860         }
2861     }
2862 
2863     //opAssign(null)
2864     nothrow @safe @nogc unittest{
2865         {
2866             RcPtr!long x = RcPtr!long.make(1);
2867 
2868             assert(x.useCount == 1);
2869             x = null;
2870             assert(x.useCount == 0);
2871             assert(x == null);
2872         }
2873 
2874         {
2875             RcPtr!(shared long) x = RcPtr!(shared long).make(1);
2876 
2877             assert(x.useCount == 1);
2878             x = null;
2879             assert(x.useCount == 0);
2880             assert(x == null);
2881         }
2882 
2883         import btl.internal.mutex : supportMutex;
2884         static if(supportMutex){
2885             shared RcPtr!(long) x = RcPtr!(shared long).make(1);
2886 
2887             assert(x.useCount == 1);
2888             x = null;
2889             assert(x.useCount == 0);
2890             assert(x.load == null);
2891         }
2892     }
2893 
2894     //useCount
2895     pure nothrow @safe @nogc unittest{
2896         RcPtr!long x = null;
2897 
2898         assert(x.useCount == 0);
2899 
2900         x = RcPtr!long.make(123);
2901         assert(x.useCount == 1);
2902 
2903         auto y = x;
2904         assert(x.useCount == 2);
2905 
2906         auto w1 = x.weak;    //weak ptr
2907         assert(x.useCount == 2);
2908 
2909         RcPtr!long.WeakType w2 = x;   //weak ptr
2910         assert(x.useCount == 2);
2911 
2912         y = null;
2913         assert(x.useCount == 1);
2914 
2915         x = null;
2916         assert(x.useCount == 0);
2917         assert(w1.useCount == 0);
2918     }
2919 
2920     //weakCount
2921     pure nothrow @safe @nogc unittest{
2922 
2923         RcPtr!long x = null;
2924         assert(x.useCount == 0);
2925         assert(x.weakCount == 0);
2926 
2927         x = RcPtr!long.make(123);
2928         assert(x.useCount == 1);
2929         assert(x.weakCount == 0);
2930 
2931         auto w = x.weak();
2932         assert(x.useCount == 1);
2933         assert(x.weakCount == 1);
2934     }
2935 
2936     // store:
2937     nothrow @nogc unittest{
2938 
2939         //null store:
2940         {
2941             shared x = RcPtr!(shared long).make(123);
2942             assert(x.load.get == 123);
2943 
2944             x.store(null);
2945             assert(x.useCount == 0);
2946             assert(x.load == null);
2947         }
2948 
2949         //rvalue store:
2950         {
2951             shared x = RcPtr!(shared long).make(123);
2952             assert(x.load.get == 123);
2953 
2954             x.store(RcPtr!(shared long).make(42));
2955             assert(x.load.get == 42);
2956         }
2957 
2958         //lvalue store:
2959         {
2960             shared x = RcPtr!(shared long).make(123);
2961             auto y = RcPtr!(shared long).make(42);
2962 
2963             assert(x.load.get == 123);
2964             assert(y.load.get == 42);
2965             assert(x.useCount == 1);
2966 
2967             x.store(y);
2968             assert(x.load.get == 42);
2969             assert(x.useCount == 2);
2970         }
2971     }
2972 
2973     //load:
2974     nothrow @nogc unittest{
2975 
2976         shared RcPtr!(long) x = RcPtr!(shared long).make(123);
2977 
2978         import btl.internal.mutex : supportMutex;
2979         static if(supportMutex){
2980             RcPtr!(shared long) y = x.load();
2981             assert(y.useCount == 2);
2982 
2983             assert(y.get == 123);
2984         }
2985 
2986     }
2987 
2988     //exchange
2989     nothrow @nogc unittest{
2990 
2991         //lvalue exchange
2992         {
2993             shared x = RcPtr!(shared long).make(123);
2994             auto y = RcPtr!(shared long).make(42);
2995 
2996             auto z = x.exchange(y);
2997 
2998             assert(x.load.get == 42);
2999             assert(y.get == 42);
3000             assert(z.get == 123);
3001         }
3002 
3003         //rvalue exchange
3004         {
3005             shared x = RcPtr!(shared long).make(123);
3006             auto y = RcPtr!(shared long).make(42);
3007 
3008             import core.lifetime : move;
3009             auto z = x.exchange(y.move);
3010 
3011             assert(x.load.get == 42);
3012             assert(y == null);
3013             assert(z.get == 123);
3014         }
3015 
3016         //null exchange (same as move)
3017         {
3018             shared x = RcPtr!(shared long).make(123);
3019 
3020             auto z = x.exchange(null);
3021 
3022             assert(x.load == null);
3023             assert(z.get == 123);
3024         }
3025 
3026         //swap:
3027         {
3028             shared x = RcPtr!(shared long).make(123);
3029             auto y = RcPtr!(shared long).make(42);
3030 
3031             //opAssign is same as store
3032             import core.lifetime : move;
3033             y = x.exchange(y.move);
3034 
3035             assert(x.load.get == 42);
3036             assert(y.get == 123);
3037         }
3038 
3039     }
3040 
3041 
3042     //compareExchange
3043     pure nothrow @nogc unittest{
3044         static class Foo{
3045             long i;
3046             this(long i)pure nothrow @safe @nogc{
3047                 this.i = i;
3048             }
3049 
3050             bool opEquals(this This)(long i)const @trusted{
3051                 import std.traits : Unqual;
3052                 auto self = cast(Unqual!This)this;
3053                 return (self.i == i);
3054             }
3055 
3056 
3057         }
3058         alias Type = const Foo;
3059         static foreach(enum bool weak; [true, false]){
3060             //fail
3061             {
3062                 RcPtr!Type a = RcPtr!Type.make(123);
3063                 RcPtr!Type b = RcPtr!Type.make(42);
3064                 RcPtr!Type c = RcPtr!Type.make(666);
3065 
3066                 static if(weak)a.compareExchangeWeak(b, c);
3067                 else a.compareExchangeStrong(b, c);
3068 
3069                 assert(*a == 123);
3070                 assert(*b == 123);
3071                 assert(*c == 666);
3072 
3073             }
3074 
3075             //success
3076             {
3077                 RcPtr!Type a = RcPtr!Type.make(123);
3078                 RcPtr!Type b = a;
3079                 RcPtr!Type c = RcPtr!Type.make(666);
3080 
3081                 static if(weak)a.compareExchangeWeak(b, c);
3082                 else a.compareExchangeStrong(b, c);
3083 
3084                 assert(*a == 666);
3085                 assert(*b == 123);
3086                 assert(*c == 666);
3087             }
3088 
3089             //shared fail
3090             {
3091                 shared RcPtr!(shared Type) a = RcPtr!(shared Type).make(123);
3092                 RcPtr!(shared Type) b = RcPtr!(shared Type).make(42);
3093                 RcPtr!(shared Type) c = RcPtr!(shared Type).make(666);
3094 
3095                 static if(weak)a.compareExchangeWeak(b, c);
3096                 else a.compareExchangeStrong(b, c);
3097 
3098                 auto tmp = a.exchange(null);
3099                 assert(*tmp == 123);
3100                 assert(*b == 123);
3101                 assert(*c == 666);
3102             }
3103 
3104             //shared success
3105             {
3106                 RcPtr!(shared Type) b = RcPtr!(shared Type).make(123);
3107                 shared RcPtr!(shared Type) a = b;
3108                 RcPtr!(shared Type) c = RcPtr!(shared Type).make(666);
3109 
3110                 static if(weak)a.compareExchangeWeak(b, c);
3111                 else a.compareExchangeStrong(b, c);
3112 
3113                 auto tmp = a.exchange(null);
3114                 assert(*tmp == 666);
3115                 assert(*b == 123);
3116                 assert(*c == 666);
3117             }
3118         }
3119 
3120     }
3121 
3122     //lock
3123     nothrow @nogc unittest{
3124         {
3125             RcPtr!long x = RcPtr!long.make(123);
3126 
3127             auto w = x.weak;    //weak ptr
3128 
3129             RcPtr!long y = w.lock;
3130 
3131             assert(x == y);
3132             assert(x.useCount == 2);
3133             assert(y.get == 123);
3134         }
3135 
3136         {
3137             RcPtr!long x = RcPtr!long.make(123);
3138 
3139             auto w = x.weak;    //weak ptr
3140 
3141             assert(w.expired == false);
3142 
3143             x = RcPtr!long.make(321);
3144 
3145             assert(w.expired == true);
3146 
3147             RcPtr!long y = w.lock;
3148 
3149             assert(y == null);
3150         }
3151         {
3152             shared RcPtr!(shared long) x = RcPtr!(shared long).make(123);
3153 
3154             shared RcPtr!(shared long).WeakType w = x.load.weak;    //weak ptr
3155 
3156             assert(w.expired == false);
3157 
3158             x = RcPtr!(shared long).make(321);
3159 
3160             assert(w.expired == true);
3161 
3162             RcPtr!(shared long) y = w.load.lock;
3163 
3164             assert(y == null);
3165         }
3166     }
3167 
3168     //expired
3169     nothrow @nogc unittest{
3170         {
3171             RcPtr!long x = RcPtr!long.make(123);
3172 
3173             auto wx = x.weak;   //weak pointer
3174 
3175             assert(wx.expired == false);
3176 
3177             x = null;
3178 
3179             assert(wx.expired == true);
3180         }
3181     }
3182 
3183     //make
3184     pure nothrow @nogc unittest{
3185         {
3186             RcPtr!long a = RcPtr!long.make();
3187             assert(a.get == 0);
3188 
3189             RcPtr!(const long) b = RcPtr!long.make(2);
3190             assert(b.get == 2);
3191         }
3192 
3193         {
3194             static struct Struct{
3195                 int i = 7;
3196 
3197                 this(int i)pure nothrow @safe @nogc{
3198                     this.i = i;
3199                 }
3200             }
3201 
3202             RcPtr!Struct s1 = RcPtr!Struct.make();
3203             assert(s1.get.i == 7);
3204 
3205             RcPtr!Struct s2 = RcPtr!Struct.make(123);
3206             assert(s2.get.i == 123);
3207         }
3208 
3209         static interface Interface{
3210         }
3211         static class Class : Interface{
3212             int i;
3213 
3214             this(int i)pure nothrow @safe @nogc{
3215                 this.i = i;
3216             }
3217         }
3218 
3219         {
3220 
3221             RcPtr!Interface x = RcPtr!Class.make(3);
3222             //assert(x.dynTo!Class.get.i == 3);
3223         }
3224 
3225 
3226     }
3227 
3228     //make dynamic array
3229     pure nothrow @nogc unittest{
3230         {
3231             auto arr = RcPtr!(long[]).make(6, -1);
3232             assert(arr.length == 6);
3233             assert(arr.get.length == 6);
3234 
3235             import std.algorithm : all;
3236             assert(arr.get.all!(x => x == -1));
3237 
3238             for(int i = 0; i < 6; ++i)
3239                 arr.get[i] = i;
3240 
3241             assert(arr.get == [0, 1, 2, 3, 4, 5]);
3242         }
3243 
3244         {
3245             static struct Struct{
3246                 int i;
3247                 double d;
3248             }
3249 
3250             {
3251                 auto a = RcPtr!(Struct[]).make(6, 42, 3.14);
3252                 assert(a.length == 6);
3253                 assert(a.get.length == 6);
3254 
3255                 import std.algorithm : all;
3256                 assert(a.get[].all!(x => (x.i == 42 && x.d == 3.14)));
3257             }
3258 
3259             {
3260                 auto a = RcPtr!(Struct[]).make(6);
3261                 assert(a.length == 6);
3262 
3263                 import std.algorithm : all;
3264                 assert(a.get[].all!(x => (x.i == int.init)));
3265             }
3266         }
3267 
3268         {
3269             static class Class{
3270                 int i;
3271                 double d;
3272 
3273                 this(int i, double d){
3274                     this.i = i;
3275                     this.d = d;
3276                 }
3277             }
3278 
3279             {
3280                 auto a = RcPtr!(Class[]).make(6, null);
3281                 assert(a.length == 6);
3282 
3283                 import std.algorithm : all;
3284                 assert(a.get[].all!(x => x is null));
3285             }
3286 
3287             {
3288                 auto a = RcPtr!(Class[]).make(6);
3289                 assert(a.length == 6);
3290 
3291                 import std.algorithm : all;
3292                 assert(a.get[].all!(x => x is null));
3293             }
3294 
3295 
3296         }
3297     }
3298 
3299     //make static array
3300     pure nothrow @nogc unittest{
3301         import std.algorithm : all;
3302         {
3303             RcPtr!(long[6]) a = RcPtr!(long[6]).make();
3304             assert(a.get.length == 6);
3305             assert(a.get[].all!(x => x == long.init));
3306         }
3307         {
3308             RcPtr!(long[6]) a = RcPtr!(long[6]).make(-1);
3309             assert(a.get.length == 6);
3310             assert(a.get[].all!(x => x == -1));
3311         }
3312         {
3313             long[6] tmp = [1, 2, 3, 4, 5, 6];
3314 
3315             RcPtr!(const(long)[6]) a = RcPtr!(long[6]).make(tmp);
3316             assert(a.get.length == 6);
3317             assert(a.get[]== tmp);
3318         }
3319         {
3320             static struct Struct{
3321                 int i;
3322                 double d;
3323             }
3324 
3325             auto a = RcPtr!(Struct[6]).make(42, 3.14);
3326             assert(a.get.length == 6);
3327 
3328             import std.algorithm : all;
3329             assert(a.get[].all!(x => (x.i == 42 && x.d == 3.14)));
3330 
3331 
3332         }
3333     }
3334 
3335     //alloc
3336     pure nothrow @nogc unittest{
3337         {
3338             TestAllocator allocator;
3339 
3340             {
3341                 RcPtr!long a = RcPtr!long.alloc(&allocator);
3342                 assert(a.get == 0);
3343 
3344                 RcPtr!(const long) b = RcPtr!long.alloc(&allocator, 2);
3345                 assert(b.get == 2);
3346             }
3347 
3348             {
3349                 static struct Struct{
3350                     int i = 7;
3351 
3352                     this(int i)pure nothrow @safe @nogc{
3353                         this.i = i;
3354                     }
3355                 }
3356 
3357                 RcPtr!Struct s1 = RcPtr!Struct.alloc(allocator);
3358                 assert(s1.get.i == 7);
3359 
3360                 RcPtr!Struct s2 = RcPtr!Struct.alloc(allocator, 123);
3361                 assert(s2.get.i == 123);
3362             }
3363 
3364             static interface Interface{
3365             }
3366             static class Class : Interface{
3367                 int i;
3368 
3369                 this(int i)pure nothrow @safe @nogc{
3370                     this.i = i;
3371                 }
3372             }
3373 
3374             {
3375 
3376 
3377                 RcPtr!Interface x = RcPtr!Class.alloc(&allocator, 3);
3378                 assert(x.useCount == 1);
3379                 //assert(x.dynTo!Class.get.i == 3);
3380             }
3381         }
3382     }
3383 
3384     //alloc
3385     unittest{
3386 
3387         {
3388             import std.experimental.allocator : allocatorObject;
3389 
3390             auto a = allocatorObject(Mallocator.instance);
3391             {
3392                 auto x = RcPtr!long.alloc(a);
3393                 assert(x.get == 0);
3394 
3395                 auto y = RcPtr!long.alloc(a, 2);
3396                 assert(y.get == 2);
3397             }
3398 
3399             {
3400                 static struct Struct{
3401                     int i = 7;
3402 
3403                     this(int i)pure nothrow @safe @nogc{
3404                         this.i = i;
3405                     }
3406                 }
3407 
3408                 auto s1 = RcPtr!Struct.alloc(a);
3409                 assert(s1.get.i == 7);
3410 
3411                 auto s2 = RcPtr!Struct.alloc(a, 123);
3412                 assert(s2.get.i == 123);
3413             }
3414 
3415             {
3416                 static interface Interface{
3417                 }
3418                 static class Class : Interface{
3419                     int i;
3420 
3421                     this(int i)pure nothrow @safe @nogc{
3422                         this.i = i;
3423                     }
3424                 }
3425 
3426                 RcPtr!(Interface, DestructorAllocatorType!(typeof(a))) x = RcPtr!Class.alloc(a, 3);
3427                 //assert(x.dynTo!Class.get.i == 3);
3428             }
3429 
3430         }
3431     }
3432 
3433     //alloc array
3434     nothrow unittest{
3435         {
3436             import std.experimental.allocator : allocatorObject;
3437 
3438             auto a = allocatorObject(Mallocator.instance);
3439             auto arr = RcPtr!(long[], DestructorAllocatorType!(typeof(a))).alloc(a, 6, -1);
3440             assert(arr.length == 6);
3441             assert(arr.get.length == 6);
3442 
3443             import std.algorithm : all;
3444             assert(arr.get.all!(x => x == -1));
3445 
3446             for(int i = 0; i < 6; ++i)
3447                 arr.get[i] = i;
3448 
3449             assert(arr.get == [0, 1, 2, 3, 4, 5]);
3450         }
3451     }
3452 
3453     //ctor
3454     pure nothrow @nogc @safe unittest{
3455 
3456         {
3457             RcPtr!long x = RcPtr!long.make(123);
3458             assert(x.useCount == 1);
3459 
3460             RcPtr!long a = x;         //lvalue copy ctor
3461             assert(a == x);
3462 
3463             const RcPtr!long b = x;   //lvalue copy ctor
3464             assert(b == x);
3465 
3466             RcPtr!(const long) c = x; //lvalue ctor
3467             assert(c == x);
3468 
3469             const RcPtr!long d = a;   //lvalue ctor
3470             assert(d == x);
3471 
3472             assert(x.useCount == 5);
3473         }
3474 
3475         {
3476             import core.lifetime : move;
3477             RcPtr!long x = RcPtr!long.make(123);
3478             assert(x.useCount == 1);
3479 
3480             RcPtr!long a = move(x);        //rvalue copy ctor
3481             assert(a.useCount == 1);
3482 
3483             const RcPtr!long b = move(a);  //rvalue copy ctor
3484             assert(b.useCount == 1);
3485 
3486             /+RcPtr!(const long) c = b.load;  //rvalue ctor
3487             assert(c.useCount == 2);
3488 
3489             const RcPtr!long d = move(c);  //rvalue ctor
3490             assert(d.useCount == 2);+/
3491         }
3492 
3493         /+{
3494             import core.lifetime : move;
3495             auto u = UniquePtr!(long, SharedControlBlock).make(123);
3496 
3497             RcPtr!long s = move(u);        //rvalue copy ctor
3498             assert(s != null);
3499             assert(s.useCount == 1);
3500 
3501             RcPtr!long s2 = UniquePtr!(long, SharedControlBlock).init;
3502             assert(s2 == null);
3503 
3504         }+/
3505 
3506     }
3507 
3508     //weak
3509     pure nothrow @nogc unittest{
3510         RcPtr!long x = RcPtr!long.make(123);
3511         assert(x.useCount == 1);
3512         auto wx = x.weak;   //weak pointer
3513         assert(wx.expired == false);
3514         assert(wx.lock.get == 123);
3515         assert(wx.useCount == 1);
3516         x = null;
3517         assert(wx.expired == true);
3518         assert(wx.useCount == 0);
3519 
3520     }
3521 
3522     //operator *
3523     pure nothrow @nogc unittest{
3524 
3525         RcPtr!long x = RcPtr!long.make(123);
3526         assert(*x == 123);
3527         (*x = 321);
3528         assert(*x == 321);
3529         const y = x;
3530         assert(*y == 321);
3531         assert(*x == 321);
3532         static assert(is(typeof(*y) == const long));
3533     }
3534 
3535     //get
3536     pure nothrow @nogc unittest{
3537         RcPtr!long x = RcPtr!long.make(123);
3538         assert(x.get == 123);
3539         x.get = 321;
3540         assert(x.get == 321);
3541         const y = x;
3542         assert(y.get == 321);
3543         assert(x.get == 321);
3544         static assert(is(typeof(y.get) == const long));
3545     }
3546 
3547     //element
3548     pure nothrow @nogc unittest{
3549         {
3550             RcPtr!long x = RcPtr!long.make(123);
3551             assert(*x.element == 123);
3552 
3553             x.get = 321;
3554             assert(*x.element == 321);
3555 
3556             const y = x;
3557             assert(*y.element == 321);
3558             assert(*x.element == 321);
3559 
3560             static assert(is(typeof(y.element) == const(long)*));
3561         }
3562 
3563         {
3564             auto x = RcPtr!(long[]).make(6, 42);
3565             assert(x.element[0] == 42);
3566             static assert(is(typeof(x.element) == long[]));
3567         }
3568 
3569         {
3570             auto s = RcPtr!long.make(42);
3571             const w = s.weak;
3572 
3573             assert(*w.element == 42);
3574 
3575             s = null;
3576             assert(w.element is null);
3577         }
3578 
3579         {
3580             auto s = RcPtr!long.make(42);
3581             auto w = s.weak;
3582 
3583             scope const p = w.element;
3584 
3585             s = null;
3586             assert(w.element is null);
3587 
3588             assert(p !is null); //p is dangling pointer!
3589         }
3590     }
3591 
3592     //ptr
3593     pure nothrow @nogc unittest{
3594         {
3595             RcPtr!long x = RcPtr!long.make(123);
3596             assert(*x.ptr == 123);
3597 
3598             x.get = 321;
3599             assert(*x.ptr == 321);
3600 
3601             const y = x;
3602             assert(*y.ptr == 321);
3603             assert(*x.ptr == 321);
3604 
3605             static assert(is(typeof(y.ptr) == const(long)*));
3606         }
3607 
3608         {
3609             auto x = RcPtr!(long[]).make(6, 42);
3610             assert(*x.ptr == 42);
3611             static assert(is(typeof(x.ptr) == long*));
3612         }
3613 
3614         {
3615             auto s = RcPtr!long.make(42);
3616             const w = s.weak;
3617 
3618             assert(*w.ptr == 42);
3619 
3620             s = null;
3621             assert(w.ptr is null);
3622         }
3623 
3624         {
3625             auto s = RcPtr!long.make(42);
3626             auto w = s.weak;
3627 
3628             scope const p = w.ptr;
3629 
3630             s = null;
3631             assert(w.ptr is null);
3632 
3633             assert(p !is null); //p is dangling pointer!
3634         }
3635     }
3636 
3637     //opCast bool
3638     @safe pure nothrow @nogc unittest{
3639         RcPtr!long x = RcPtr!long.make(123);
3640         assert(cast(bool)x);    //explicit cast
3641         assert(x);              //implicit cast
3642         x = null;
3643         assert(!cast(bool)x);   //explicit cast
3644         assert(!x);             //implicit cast
3645     }
3646 
3647     //opCast RcPtr
3648     /+TODO
3649     @safe pure nothrow @nogc unittest{
3650         RcPtr!long x = RcPtr!long.make(123);
3651         auto y = cast(RcPtr!(const long))x;
3652         auto z = cast(const RcPtr!long)x;
3653         auto u = cast(const RcPtr!(const long))x;
3654         assert(x.useCount == 4);
3655     }
3656     +/
3657 
3658     //opEquals RcPtr
3659     pure @safe nothrow @nogc unittest{
3660         {
3661             RcPtr!long x = RcPtr!long.make(0);
3662             assert(x != null);
3663             x = null;
3664             assert(x == null);
3665         }
3666 
3667         {
3668             RcPtr!long x = RcPtr!long.make(123);
3669             RcPtr!long y = RcPtr!long.make(123);
3670             assert(x == x);
3671             assert(y == y);
3672             assert(x != y);
3673         }
3674 
3675         {
3676             RcPtr!long x;
3677             RcPtr!(const long) y;
3678             assert(x == x);
3679             assert(y == y);
3680             assert(x == y);
3681         }
3682     }
3683 
3684     //opEquals RcPtr
3685     pure nothrow @nogc unittest{
3686         {
3687             RcPtr!long x = RcPtr!long.make(123);
3688             RcPtr!long y = RcPtr!long.make(123);
3689             assert(x == x.element);
3690             assert(y.element == y);
3691             assert(x != y.element);
3692         }
3693     }
3694 
3695     //opCmp
3696     pure nothrow @safe @nogc unittest{
3697         {
3698             const a = RcPtr!long.make(42);
3699             const b = RcPtr!long.make(123);
3700             const n = RcPtr!long.init;
3701 
3702             assert(a <= a);
3703             assert(a >= a);
3704 
3705             assert((a < b) == !(a >= b));
3706             assert((a > b) == !(a <= b));
3707 
3708             assert(a > n);
3709             assert(a > null);
3710 
3711             assert(n < a);
3712             assert(null < a);
3713         }
3714     }
3715 
3716     //opCmp
3717     pure nothrow @nogc unittest{
3718         {
3719             const a = RcPtr!long.make(42);
3720             const b = RcPtr!long.make(123);
3721 
3722             assert(a <= a.element);
3723             assert(a.element >= a);
3724 
3725             assert((a < b.element) == !(a.element >= b));
3726             assert((a > b.element) == !(a.element <= b));
3727         }
3728     }
3729 
3730     //toHash
3731     pure nothrow @safe @nogc unittest{
3732         {
3733             RcPtr!long x = RcPtr!long.make(123);
3734             RcPtr!long y = RcPtr!long.make(123);
3735             assert(x.toHash == x.toHash);
3736             assert(y.toHash == y.toHash);
3737             assert(x.toHash != y.toHash);
3738             RcPtr!(const long) z = x;
3739             assert(x.toHash == z.toHash);
3740         }
3741         {
3742             RcPtr!long x;
3743             RcPtr!(const long) y;
3744             assert(x.toHash == x.toHash);
3745             assert(y.toHash == y.toHash);
3746             assert(x.toHash == y.toHash);
3747         }
3748     }
3749 
3750     //proxySwap
3751     pure nothrow @nogc unittest{
3752         {
3753             RcPtr!long a = RcPtr!long.make(1);
3754             RcPtr!long b = RcPtr!long.make(2);
3755             a.proxySwap(b);
3756             assert(*a == 2);
3757             assert(*b == 1);
3758             import std.algorithm : swap;
3759             swap(a, b);
3760             assert(*a == 1);
3761             assert(*b == 2);
3762             assert(a.useCount == 1);
3763             assert(b.useCount == 1);
3764         }
3765     }
3766 
3767     //length
3768     pure nothrow @nogc unittest{
3769         auto x = RcPtr!(int[]).make(10, -1);
3770         assert(x.length == 10);
3771         assert(x.get.length == 10);
3772 
3773         import std.algorithm : all;
3774         assert(x.get.all!(i => i == -1));
3775     }
3776 
3777 }
3778 
3779 pure nothrow @safe @nogc unittest{
3780     RcPtr!void u = RcPtr!void.make();
3781 }
3782 
3783 
3784 version(unittest){
3785     struct Foo{
3786         RcPtr!int i;
3787     }
3788 }
3789 
3790 
3791 
3792 //test strong ptr -> weak ptr move ctor
3793 unittest{
3794     {
3795         import core.lifetime : move;
3796 
3797         auto a = RcPtr!int.make(1);
3798         auto b = a;
3799         assert(a.useCount == 2);
3800         assert(a.weakCount == 0);
3801 
3802         RcPtr!int.WeakType x = move(a);
3803         assert(b.useCount == 1);
3804         assert(b.weakCount == 1);
3805     }
3806 }
3807 
3808 //test strong ptr -> weak ptr assign
3809 unittest{
3810     {
3811         import core.lifetime : move;
3812 
3813         auto a = RcPtr!int.make(1);
3814         auto b = RcPtr!int.make(2);
3815 
3816         {
3817             RcPtr!int.WeakType x = RcPtr!int(a);
3818             assert(a.useCount == 1);
3819             assert(a.weakCount == 1);
3820 
3821             x = RcPtr!int(b);
3822             assert(a.useCount == 1);
3823             assert(a.weakCount == 0);
3824 
3825             assert(b.useCount == 1);
3826             assert(b.weakCount == 1);
3827         }
3828         {
3829             RcPtr!int.WeakType x = a;
3830             assert(a.useCount == 1);
3831             assert(a.weakCount == 1);
3832 
3833             RcPtr!int.WeakType y = b;
3834             assert(b.useCount == 1);
3835             assert(b.weakCount == 1);
3836 
3837             x = y;
3838             assert(a.useCount == 1);
3839             assert(a.weakCount == 0);
3840 
3841             assert(b.useCount == 1);
3842             assert(b.weakCount == 2);
3843 
3844 
3845         }
3846     }
3847 }
3848 
3849 //compare strong and weak ptr
3850 unittest{
3851     auto a = RcPtr!int.make(1);
3852     auto b = a.weak;
3853     assert(a == b);
3854 }
3855 
3856 //self opAssign
3857 unittest{
3858     auto a = RcPtr!long.make(1);
3859     a = a;
3860 }
3861 
3862 version(unittest){
3863 //debug{
3864     private struct Cycle{
3865 
3866         RcPtr!(Cycle, DestructorType!void, SharedControlBlock) cycle;
3867 
3868         ~this()pure nothrow @safe @nogc{}
3869     }
3870 }