Merge pull request #4938 from kumpera/optimize_ref_queries
[mono.git] / mono / tests / bug-561239.cs
1 using System;
2 using System.IO;
3 using System.Threading;
4
5 public class PulseTest
6 {
7         private bool   startedUp = false;
8         private int    threadNum = 0;
9         private object theLock   = new object ();
10
11         public static void Main (string[] args)
12         {
13                 int lastThreadNum = 0;
14
15                 for (int i = 0; i < 100; ++i) {
16                         /*
17                          * Start a thread going.
18                          */
19                         PulseTest pulseTest = new PulseTest ();
20                         pulseTest.threadNum = ++ lastThreadNum;
21                         Thread sysThread = new Thread (pulseTest.ThreadMain);
22
23                         /*
24                          * Block thread from doing anything.
25                          */
26                         Monitor.Enter (pulseTest.theLock);
27
28                         /*
29                          * Now start it.
30                          */
31                         sysThread.Start ();
32
33                         /*
34                          * Wait for pulsetest thread to call Monitor.Wait().
35                          */
36                         while (!pulseTest.startedUp) {
37                                 pulseTest.Message ("Main", "waiting");
38                                 Monitor.Wait (pulseTest.theLock);
39                                 pulseTest.Message ("Main", "woken");
40                         }
41                         Monitor.Exit (pulseTest.theLock);
42
43                         /*
44                          * Whilst it is sitting in Monitor.Wait, kill it off.
45                          *
46                          * Without the patch, the wait event sits in mon->wait_list,
47                          * even as the mon struct gets recycled onto monitor_freelist.
48                          *
49                          * With the patch, the event is unlinked when the mon struct
50                          * gets recycled.
51                          */
52                         pulseTest.Message ("Main", "disposing");
53                         sysThread.Abort ();
54                         sysThread.Join ();
55                         pulseTest.Message ("Main", "disposed");
56                 }
57         }
58
59         private void ThreadMain ()
60         {
61                 Monitor.Enter (theLock);
62                 startedUp = true;
63                 Monitor.Pulse (theLock);
64                 while (true) {
65                         Message ("ThreadMain", "waiting");
66
67                         /*
68                          * This puts an event onto mon->wait_list.
69                          * Then Main() does a sysThread.Abort() and
70                          * the event is left on mon->wait_list.
71                          */
72                         Monitor.Wait (theLock);
73                         Message ("ThreadMain", "woken");
74                 }
75         }
76
77         private void Message (string func, string msg)
78         {
79                 Console.WriteLine ("{0}[{1}]*: {2}", func, threadNum, msg);
80         }
81 }