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