1 module yu.memory.smartref;
2 
3 import std.experimental.allocator;
4 
5 public import yu.memory.scopedref;
6 public import yu.memory.sharedref;
7 public import yu.memory.allocator.smartgcalloctor;
8 import yu.traits;
9 
10 alias SharedRef(T) = ISharedRef!(SmartGCAllocator, T,true);
11 alias WeakRef(T) = IWeakRef!(SmartGCAllocator, T,true);
12 alias ScopedRef(T) = IScopedRef!(SmartGCAllocator, T);
13 
14 // alias
15 pragma(inline, true) auto makeSharedRef(T, Args...)(auto ref Args args) {
16     return SharedRef!(T)(SmartGCAllocator.instance.make!T(args));
17 }
18 
19 pragma(inline, true) auto makeScopedRef(T, Args...)(auto ref Args args) {
20     return ScopedRef!(T)(SmartGCAllocator.instance.make!T(args));
21 }
22 
23 pragma(inline, true) auto makeSharedRefWithDeleter(T, Args...)(auto ref Args args) {
24     static assert(args.length > 0);
25     static assert(is(typeof(args[0]) == void function(ref typeof(SmartGCAllocator.instance), Pointer!T) ));
26     return SharedRef!(T)(SmartGCAllocator.instance.make!T(args[1 .. $]), args[0]);
27 }
28 
29 pragma(inline, true) auto makeScopedRefWithDeleter(T, Args...)(auto ref Args args) {
30     static assert(args.length > 0);
31     static assert(is(typeof(args[0]) == void function(ref typeof(SmartGCAllocator.instance), Pointer!T)));
32     return ScopedRef!(T)(SmartGCAllocator.instance.make!T(args[1 .. $]), args[0]);
33 }
34 
35 // I
36 pragma(inline, true) auto makeISharedRef(T, Alloc, Args...)(auto ref Alloc alloc, auto ref Args args) {
37     Pointer!T value = alloc.make!T(args);
38     static if (stateSize!Alloc == 0) {
39         return ISharedRef!(Alloc, T)(value);
40     } else {
41         return ISharedRef!(Alloc, T)(alloc, value);
42     }
43 }
44 
45 pragma(inline, true) auto makeIScopedRef(T, Alloc, Args...)(auto ref Alloc alloc, auto ref Args args) {
46     Pointer!T value = alloc.make!T(args);
47     static if (stateSize!Alloc == 0) {
48         return IScopedRef!(Alloc, T)(value);
49     } else {
50         return IScopedRef!(Alloc, T)(alloc, value);
51     }
52 }
53 
54 pragma(inline, true) auto makeISharedRefWithDeleter(T, Alloc, Args...)(
55     auto ref Alloc alloc, auto ref Args args) {
56     static assert(args.length > 0);
57     static assert(is(typeof(args[0]) == void function(ref Alloc, Pointer!T)));
58     Pointer!T value = alloc.make!T(args[1 .. $]);
59     static if (stateSize!Alloc == 0) {
60         return ISharedRef!(Alloc, T)(value, args[0]);
61     } else {
62         return ISharedRef!(Alloc, T)(alloc, value, args[0]);
63     }
64 }
65 
66 pragma(inline, true) auto makeIScopedRefWithDeleter(T, Alloc, Args...)(
67     auto ref Alloc alloc, auto ref Args args) {
68     static assert(args.length > 0);
69     static assert(is(typeof(args[0]) == void function(ref Alloc, Pointer!T)));
70     Pointer!T value = alloc.make!T(args[1 .. $]);
71     static if (stateSize!Alloc == 0) {
72         return IScopedRef!(Alloc, T)(value, args[0]);
73     } else {
74         return IScopedRef!(Alloc, T)(alloc, value, args[0]);
75     }
76 }
77 
78 mixin template EnableSharedFromThisImpl(Alloc,T, bool Shread = true)
79 {
80     alias TWeakRef = IWeakRef!(Alloc,T,Shread);
81 	alias TSharedRef = ISharedRef!(Alloc,T,Shread);
82 public:
83 	pragma(inline,true)
84 	final TSharedRef sharedFromThis() { return TSharedRef(__weakPointer); }
85     
86 	final void __InitializeFromSharedPointer(SHARED)(auto ref SHARED  ptr)
87         if(is(SHARED == struct) && SHARED.isSharedRef && __traits(isSame, SHARED.Data, TWeakRef.Data)) 
88 	{
89 		__weakPointer = ptr;
90 	}
91 
92 private TWeakRef __weakPointer;
93 }
94 
95 version (unittest) {
96     import std.stdio;
97     import std.experimental.allocator;
98     import std.experimental.allocator.gc_allocator;
99     import std.exception;
100 
101     void smartfreeSharedInt(ref typeof(SmartGCAllocator.instance) alloc, int* d)  {
102        writeln("free the int"); 
103        alloc.dispose(d);
104     }
105 
106     void freeSharedInt(ref typeof(GCAllocator.instance) alloc, int* d) {
107         writeln("free the int");
108          alloc.dispose(d); 
109     }
110 
111     class TestMyClass  {
112         mixin EnableSharedFromThisImpl!(SmartGCAllocator,typeof(this));
113         shared this(int t) {
114             i = t;
115             writeln("create TestMyClass i = ", i);
116         }
117 
118         this(int t) {
119             i = t;
120             writeln("create TestMyClass i = ", i);
121         }
122 
123         ~this() {
124             writeln("free TestMyClass i = ", i);
125         }
126 
127         int i = 0;
128     }
129 }
130 
131 
132 unittest {
133     import std.stdio;
134     import std.experimental.allocator;
135     import std.experimental.allocator.gc_allocator;
136     import std.exception;
137 
138     {
139         //auto malloc = 
140         auto a = GCAllocator.instance.makeISharedRefWithDeleter!(int)(&freeSharedInt,
141             10);
142         assert(*a == 10);
143         auto c = a.castTo!(uint)();
144         *c = uint.max;
145         uint t = cast(uint)(*a);
146         assert(t == uint.max);
147         auto b = GCAllocator.instance.makeISharedRef!int(100);
148         assert(*b == 100);
149         auto a1 = makeSharedRefWithDeleter!(int)(&smartfreeSharedInt, 10);
150         assert(*a1 == 10);
151         auto b1 = makeSharedRef!int(100);
152         assert(*b1 == 100);
153 
154     }
155     writeln("Edit source/app.d to start your project.");
156 
157     auto a = makeIScopedRefWithDeleter!(int)(GCAllocator.instance, &freeSharedInt);
158     auto a1 = makeScopedRefWithDeleter!(int)(&smartfreeSharedInt);
159     {
160         auto aclass = makeScopedRef!(TestMyClass)(10);
161         aclass.i = 500;
162     }
163 
164     {
165         auto sclass = makeSharedRef!(shared TestMyClass)(100);
166         sclass.i = 1000;
167 
168         auto sobj = sclass.castTo!(shared Object)();
169         //auto nsared = sclass.castTo!(TestMyClass)(); , erro mast all sheref or not
170 
171         auto t = makeSharedRef!(TestMyClass)(400);
172         t.i = 50;
173         auto th = t.sharedFromThis();
174         auto tobj = th.castTo!(Object)();
175         th.i = 30;
176     }
177 }