Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / tests / gchandles.cs
1 using System;
2 using System.Threading;
3 using System.Runtime.InteropServices;
4
5 [StructLayout(LayoutKind.Explicit)]
6 internal struct ObjectWrapper {
7         [FieldOffset(0)] object obj;
8         [FieldOffset(0)] IntPtr handle;
9
10         internal static IntPtr Convert (object obj) {
11                 ObjectWrapper wrapper = new ObjectWrapper ();
12
13                 wrapper.obj = obj;
14
15                 return wrapper.handle;
16         }
17         
18         internal static object Convert (IntPtr ptr) 
19         {
20                 ObjectWrapper wrapper = new ObjectWrapper ();
21                 
22                 wrapper.handle = ptr;
23                         
24                 return wrapper.obj;
25         }
26 }
27
28 public class Test1
29 {
30         public GCHandle self;
31         public static bool fail;
32         public static Test1 instance;
33
34         ~Test1 () {
35                 if (self.Target == null)
36                         fail = true;
37         }
38 }
39
40 public class Test2
41 {
42         public GCHandle self;
43         public static bool fail;
44         public static Test2 instance;
45
46         ~Test2 () {
47                 if (self.Target == null)
48                         fail = true;
49         }
50 }
51
52 public class Tests
53 {
54         public static int Main (String[] args) {
55                 return TestDriver.RunTests (typeof (Tests), args);
56         }
57
58         static void create1 () {
59                 Test1.instance = new Test1 ();
60                 Test1.instance.self = GCHandle.Alloc (Test1.instance, GCHandleType.WeakTrackResurrection);
61                 Test1.instance = null;
62         }
63
64         public static unsafe int test_0_track_resurrection () {
65                 /* The GCHandle should not be cleared before calling the finalizers */
66                 create1 ();
67                 GC.Collect ();
68                 GC.WaitForPendingFinalizers ();
69
70                 // WaitForPendingFinalizers doesn't seem to work ?
71                 System.Threading.Thread.Sleep (100);
72                 /* If the finalizers do not get ran by this time, the test will still succeed */
73                 return Test1.fail ? 1 : 0;
74         }
75
76         static void create2 () {
77                 Test2.instance = new Test2 ();
78                 object o = new object ();
79                 Test2.instance.self = GCHandle.Alloc (o, GCHandleType.WeakTrackResurrection);
80                 Test2.instance.self.Target = Test2.instance;
81                 Test2.instance = null;
82         }
83
84         public static int test_0_track_resurrection_set_target () {
85                 /* Same test but the handle target is set dynamically after it is created */
86                 create2 ();
87                 GC.Collect ();
88                 GC.WaitForPendingFinalizers ();
89
90                 System.Threading.Thread.Sleep (100);
91                 return Test2.fail ? 1 : 0;
92         }
93
94         static GCHandle handle;
95         static IntPtr original_addr;
96         
97         static void alloc_handle () {
98                 var obj = new object ();
99                 handle = GCHandle.Alloc (obj, GCHandleType.Pinned);
100                 original_addr =  ObjectWrapper.Convert (obj);
101         }
102
103         public static int test_0_pinned_handle_pins_target () {
104                 var t = new Thread (alloc_handle);
105                 t.Start ();
106                 t.Join ();
107                 GC.Collect ();
108
109                 var newAddr = ObjectWrapper.Convert (handle.Target);
110
111                 return original_addr == newAddr ? 0 : 1;
112         }
113 }