Merge pull request #2819 from BrzVlad/fix-major-log
[mono.git] / mono / tests / sgen-toggleref.cs
1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.Threading;
5 using System.Runtime.InteropServices;
6 using System.Runtime.CompilerServices;
7
8 public class Toggleref {
9         public int __test;
10         public string id;
11         public List<object> link = new List<object> ();
12         public const int DROP = 0;
13         public const int STRONG = 1;
14         public const int WEAK = 2;
15         
16         ~Toggleref () {
17
18         }
19 }
20
21 [StructLayout (LayoutKind.Explicit)]
22 public struct Helper {
23         [FieldOffset(0)]
24         IntPtr ptr;
25         [FieldOffset(0)]
26         object obj;
27         public static IntPtr ObjToPtr (object obj)
28         {
29                 Helper h = default (Helper);
30                 h.obj = obj;
31                 return h.ptr;
32         }
33 }
34
35 class Driver {
36         static WeakReference<Toggleref> root, child;
37
38         [DllImport ("__Internal", EntryPoint="mono_gc_toggleref_add")]
39         static extern int mono_gc_toggleref_add (IntPtr ptr, bool strong_ref);
40
41         static void Register (object obj)
42         {
43                 mono_gc_toggleref_add (Helper.ObjToPtr (obj), true);
44         }
45
46         static Toggleref a, b;
47
48         static void SetupLinks () {
49                 var r = new Toggleref () { id = "root" };
50                 var c = new Toggleref () { id = "child" };
51                 r.link.Add (c);
52                 r.__test = Toggleref.STRONG;
53                 c.__test = Toggleref.WEAK;
54                 Register (r);
55                 Register (c);
56                 root = new WeakReference<Toggleref> (r, false);
57                 child = new WeakReference<Toggleref> (c, false);
58         }
59
60         static int test_0_root_keeps_child ()
61         {
62                 Console.WriteLine ("test_0_root_keeps_child");
63                 var t = new Thread (SetupLinks);
64                 t.Start ();
65                 t.Join ();
66                 
67                 GC.Collect ();
68                 GC.WaitForPendingFinalizers ();
69
70                 Console.WriteLine ("try get A {0}", root.TryGetTarget (out a));
71                 Console.WriteLine ("try get B {0}", child.TryGetTarget (out b));
72                 Console.WriteLine ("a is null {0}", a == null);
73                 Console.WriteLine ("b is null {0}", b == null);
74                 if (a == null || b == null)
75                         return 1;
76                 Console.WriteLine ("a test {0}", a.__test);
77                 Console.WriteLine ("b test {0}", b.__test);
78
79                 //now we break the link and switch b to strong
80                 a.link.Clear ();
81                 b.__test = Toggleref.STRONG;
82                 a = b = null;
83
84                 GC.Collect ();
85                 GC.WaitForPendingFinalizers ();
86
87                 Console.WriteLine ("try get A {0}", root.TryGetTarget (out a));
88                 Console.WriteLine ("try get B {0}", child.TryGetTarget (out b));
89                 Console.WriteLine ("a is null {0}", a == null);
90                 Console.WriteLine ("b is null {0}", b == null);
91                 if (a == null || b == null)
92                         return 2;
93                 Console.WriteLine ("a test {0}", a.__test);
94                 Console.WriteLine ("b test {0}", b.__test);
95
96
97                 return 0;
98         }
99
100         static void SetupLinks2 () {
101                 var r = new Toggleref () { id = "root" };
102                 var c = new Toggleref () { id = "child" };
103
104                 r.__test = Toggleref.STRONG;
105                 c.__test = Toggleref.WEAK;
106                 Register (r);
107                 Register (c);
108                 root = new WeakReference<Toggleref> (r, false);
109                 child = new WeakReference<Toggleref> (c, false);
110         }
111
112         static int test_0_child_goes_away ()
113         {
114                 Console.WriteLine ("test_0_child_goes_away");
115
116                 var t = new Thread (SetupLinks2);
117                 t.Start ();
118                 t.Join ();
119
120                 GC.Collect ();
121                 GC.WaitForPendingFinalizers ();
122
123                 Console.WriteLine ("try get A {0}", root.TryGetTarget (out a));
124                 Console.WriteLine ("try get B {0}", child.TryGetTarget (out b));
125                 Console.WriteLine ("a is null {0}", a == null);
126                 Console.WriteLine ("b is null {0}", b == null);
127                 if (a == null || b != null)
128                         return 1;
129                 Console.WriteLine ("a test {0}", a.__test);
130
131                 return 0;
132         }
133
134         static ConditionalWeakTable<Toggleref, object> cwt = new ConditionalWeakTable<Toggleref, object> ();
135         static WeakReference<object> root_value, child_value;
136         static object a_val, b_val;
137
138
139         static void SetupLinks3 () {
140                 var r = new Toggleref () { id = "root" };
141                 var c = new Toggleref () { id = "child" };
142
143                 r.__test = Toggleref.STRONG;
144                 c.__test = Toggleref.WEAK;
145                 Register (r);
146                 Register (c);
147                 root = new WeakReference<Toggleref> (r, false);
148                 child = new WeakReference<Toggleref> (c, false);
149
150                 var root_val = new object ();
151                 var child_val = new object ();
152
153                 cwt.Add (r, root_val);
154                 cwt.Add (c, child_val);
155
156                 root_value = new WeakReference<object> (root_val, false);
157                 child_value = new WeakReference<object> (child_val, false);
158         }
159
160         static int test_0_CWT_keep_child_alive ()
161         {
162                 Console.WriteLine ("test_0_CWT_keep_child_alive");
163
164                 var t = new Thread (SetupLinks3);
165                 t.Start ();
166                 t.Join ();
167
168                 GC.Collect ();
169                 GC.WaitForPendingFinalizers ();
170
171                 Console.WriteLine ("try get A {0}", root.TryGetTarget (out a));
172                 Console.WriteLine ("try get B {0}", child.TryGetTarget (out b));
173                 Console.WriteLine ("a is null {0}", a == null);
174                 Console.WriteLine ("b is null {0}", b == null);
175                 if (a == null || b != null)
176                         return 1;
177                 Console.WriteLine ("a test {0}", a.__test);
178
179                 Console.WriteLine ("try get a_val {0}", root_value.TryGetTarget (out a_val));
180                 Console.WriteLine ("try get v_val {0}", child_value.TryGetTarget (out b_val));
181
182                 //the strong toggleref must keep the CWT value to remains alive
183                 if (a_val == null)
184                         return 2;
185
186                 //the weak toggleref should allow the CWT value to go away
187                 if (b_val != null)
188                         return 3;
189
190                 object res_value = null;
191                 bool res = cwt.TryGetValue (a, out res_value);
192                 Console.WriteLine ("CWT result {0} -> {1}", res, res_value == a_val);
193
194                 //the strong val is not on the CWT
195                 if (!res)
196                         return 4;
197
198                 //for some reason the value is not the right one
199                 if (res_value != a_val)
200                         return 5;
201
202                 return 0;
203         }
204
205         static int Main (string[] args)
206         {
207                 return TestDriver.RunTests (typeof (Driver), args);
208         }
209
210 }