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