[sgen] Avoid popping the entire finalizer queues if finalizers are suspended
[mono.git] / mcs / class / Mono.Tasklets / Test / Mono.Tasklets / ContinuationsTest.cs
1 using NUnit.Framework;
2
3 using System;
4 using Mono.Tasklets;
5
6 namespace MonoTests.System
7 {
8     [TestFixture]
9         public class ContinuationsTest {
10
11                 private Continuation _contA = new Continuation();
12
13                 private int total = 0;
14
15                 [Test]
16                 public void TestContinuationsLoop() {
17                         _contA.Mark();
18                         int value = 0;
19                         int ret = _contA.Store(0);
20                         for(int i = ret; i < 10; i++) {
21                                 value += i;
22                         }
23
24                         if(value > 0) {
25                                 total += value;
26                                 _contA.Restore(ret + 1);
27                         }
28
29                         Assert.AreEqual(total,330);
30                 }
31
32                 private int yields = 0;
33
34                 [Test]
35                 public void Yielding() {
36                         Continuation baseCont = new Continuation();
37                         Continuation taskCont = new Continuation();
38                         
39                         baseCont.Mark();
40                         taskCont.Mark();
41                         
42                         // Store the base continuation to start the task
43                         if (baseCont.Store(0) == 0) {
44                                 bool done = false;
45                                 int count = 0;
46
47                                 while (!done) {
48                                         // Do stuff for the task.
49                                         ++count;
50                                         
51                                         // This task is counting to 100.
52                                         if (count == 100) {
53                                                 done = true;
54                                         }
55
56                                         // Yield every 10 loops
57                                         else if (count % 10 == 0) {
58
59                                                 // To yield, store the task continuation then restore
60                                                 // the base continuation.
61                                                 if (taskCont.Store(0) == 0) {
62                                                         baseCont.Restore(1);
63                                                 }
64                                         }
65                                 }
66                         }
67                         // When restored, 'Store' will return what was passed to Restore, in this case 1 so fall here.
68                         else {
69                                 // Count the yields, then go back to the task.
70                                 ++yields;
71                                 taskCont.Restore(1);
72                         }
73
74                         Assert.AreEqual(9, yields);
75                 }
76
77
78                 public class MicroThread {
79                         
80                         public void Yield() {
81                                 if (MyThread.Store(0) == 0) {
82                                         MainThread.Restore(1);
83                                 }
84                         }
85
86                         public void Resume() {
87                                 if (MainThread.Store(0) == 0) {
88                                         MyThread.Restore(1);
89                                 }
90                         }
91
92                         public void DoWork(Action action) {
93                                 if (MainThread.Store(0) == 0) {
94                                         action();
95                                         Done = true;
96                                         MainThread.Restore(1);
97                                 }
98                         }
99
100                         public bool Done = false;
101                         public Continuation MainThread = new Continuation();
102                         public Continuation MyThread = new Continuation();
103                 }
104                 
105                 public class MicroBJob {
106                         private int _Count = 0;
107                         public int Count { 
108                                 get { return _Count; }
109                                 set { _Count = value;}
110                         }
111
112                         public MicroThread MicroThread;
113                         public void Work() {
114                                 while (Count < 100) {
115                                         ++Count;
116                                         if (Count % 10 == 0) {
117                                                 MicroThread.Yield();
118                                         }
119                                 }
120                         }
121                 }
122
123                 [Test]
124                 public void MicroThreadTest() {
125                         MicroThread microA = new MicroThread();
126                         MicroThread microB = new MicroThread();
127
128                         microA.MainThread.Mark();
129                         microA.MyThread.Mark();
130                         microB.MainThread.Mark();
131                         microB.MyThread.Mark();
132
133                         Assert.AreEqual(false,microA.Done);
134                         Assert.AreEqual(false,microB.Done);
135                         
136                         microA.DoWork( () => {
137                                 int count = 0;
138                                 while (count < 100) {
139                                         ++count;
140                                         if (count % 10 == 0) {
141                                                 microA.Yield();
142                                         }
143                                 }
144                         });
145                 
146                         MicroBJob jobB = new MicroBJob();
147                         jobB.MicroThread = microB;
148
149                         microB.DoWork(jobB.Work);
150
151                         Assert.AreEqual(false,microA.Done);
152                         Assert.AreEqual(false,microB.Done);
153
154                         int yields = 0;
155                         while (yields < 20) {
156                                 if (!microA.Done) microA.Resume();
157                                 if (!microB.Done) microB.Resume();
158                                 if (microA.Done && microB.Done) break;
159                                 ++yields;
160                         }
161
162                         Assert.AreEqual(true,microA.Done);
163                         Assert.AreEqual(true,microB.Done);
164                         Assert.AreEqual(100,jobB.Count);
165                         Assert.AreEqual(9,yields);
166                 }
167         }
168 }
169
170 // vim: noexpandtab
171 // Local Variables:
172 // tab-width: 4
173 // c-basic-offset: 4
174 // indent-tabs-mode: t
175 // End: