1 static class Foo{
2 int i;
3
4 this(int i)pure nothrow @safe @nogc{
5 this.i = i;
6 }
7 }
8
9 static class Bar : Foo{
10 double d;
11
12 this(int i, double d)pure nothrow @safe @nogc{
13 super(i);
14 this.d = d;
15 }
16 }
17
18 static class Zee : Bar{
19 bool b;
20
21 this(int i, double d, bool b)pure nothrow @safe @nogc{
22 super(i, d);
23 this.b = b;
24 }
25
26 ~this()nothrow @system{
27 }
28 }
29
30 ///simple:
31 {
32 RcPtr!long a = RcPtr!long.make(42);
33 assert(a.useCount == 1);
34
35 RcPtr!(const long) b = a;
36 assert(a.useCount == 2);
37
38 RcPtr!long.WeakType w = a.weak; //or WeakRcPtr!long
39 assert(a.useCount == 2);
40 assert(a.weakCount == 1);
41
42 RcPtr!long c = w.lock;
43 assert(a.useCount == 3);
44 assert(a.weakCount == 1);
45
46 assert(*c == 42);
47 assert(c.get == 42);
48 }
49
50 ///polymorphism and aliasing:
51 {
52 ///create RcPtr
53 RcPtr!Foo foo = RcPtr!Bar.make(42, 3.14);
54 RcPtr!Zee zee = RcPtr!Zee.make(42, 3.14, false);
55
56 ///dynamic cast:
57 RcPtr!Bar bar = dynCast!Bar(foo);
58 assert(bar != null);
59 assert(foo.useCount == 2);
60
61 ///this doesnt work because Foo destructor attributes are more restrictive then Zee's:
62 //RcPtr!Foo x = zee;
63
64 ///this does work:
65 RcPtr!(Foo, DestructorType!(Foo, Zee)) x = zee;
66 assert(zee.useCount == 2);
67 }
68
69
70 ///multi threading:
71 {
72 ///create RcPtr with atomic ref counting
73 RcPtr!(shared Foo) foo = RcPtr!(shared Bar).make(42, 3.14);
74
75 ///this doesnt work:
76 //foo.get.i += 1;
77
78 import core.atomic : atomicFetchAdd;
79 atomicFetchAdd(foo.get.i, 1);
80 assert(foo.get.i == 43);
81
82
83 ///creating `shared(RcPtr)`:
84 shared RcPtr!(shared Bar) bar = share(dynCast!Bar(foo));
85
86 ///`shared(RcPtr)` is lock free (except `load` and `useCount`/`weakCount`).
87 static assert(typeof(bar).isLockFree == true);
88
89 ///multi thread operations (`load`, `store`, `exchange` and `compareExchange`):
90 RcPtr!(shared Bar) bar2 = bar.load();
91 assert(bar2 != null);
92 assert(bar2.useCount == 3);
93
94 RcPtr!(shared Bar) bar3 = bar.exchange(null);
95 assert(bar3 != null);
96 assert(bar3.useCount == 3);
97 }
98
99 ///dynamic array:
100 {
101 import std.algorithm : all, equal;
102
103 RcPtr!(long[]) a = RcPtr!(long[]).make(10, -1);
104 assert(a.length == 10);
105 assert(a.get.length == 10);
106 assert(a.get.all!(x => x == -1));
107
108 for(int i = 0; i < a.length; ++i){
109 a.get[i] = i;
110 }
111 assert(a.get[] == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
112 }//make RcPtr object
static struct Foo{
int i;
this(int i)pure nothrow @safe @nogc{
this.i = i;
}
}
{
auto foo = RcPtr!Foo.make(42);
auto foo2 = RcPtr!Foo.make!Mallocator(42); //explicit stateless allocator
}
{
auto arr = RcPtr!(long[]).make(10); //dynamic array with length 10
assert(arr.length == 10);
}//alloc RcPtr object
import std.experimental.allocator : make, dispose, allocatorObject;
auto allocator = allocatorObject(Mallocator.instance);
{
auto x = RcPtr!(long).alloc(allocator, 42);
}
{
import btl.internal.traits;
static assert(isMoveConstructableElement!(typeof(allocator)));
auto arr = RcPtr!(long[]).alloc(allocator, 10); //dynamic array with length 10
assert(arr.length == 10);
}
Alias to RcPtr with different order of template parameters