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 [TestFixtureSetUp] FixtureSetUp()12 public void FixtureSetUp () 13 { 14 try { 15 var temp = new Continuation (); 16 } catch (NotImplementedException) { 17 Assert.Ignore ("This platform doesn't support Tasklets."); 18 } 19 } 20 21 int total = 0; 22 23 [Test] TestContinuationsLoop()24 public void TestContinuationsLoop() 25 { 26 Continuation _contA = new Continuation(); 27 28 _contA.Mark(); 29 int value = 0; 30 int ret = _contA.Store(0); 31 for (int i = ret; i < 10; i++) { 32 value += i; 33 } 34 35 if (value > 0) { 36 total += value; 37 _contA.Restore(ret + 1); 38 } 39 40 Assert.AreEqual(total, 330); 41 } 42 43 private int yields = 0; 44 45 [Test] Yielding()46 public void Yielding() 47 { 48 Continuation baseCont = new Continuation(); 49 Continuation taskCont = new Continuation(); 50 51 baseCont.Mark(); 52 taskCont.Mark(); 53 54 // Store the base continuation to start the task 55 if (baseCont.Store(0) == 0) { 56 bool done = false; 57 int count = 0; 58 59 while (!done) { 60 // Do stuff for the task. 61 ++count; 62 63 // This task is counting to 100. 64 if (count == 100) { 65 done = true; 66 } 67 68 // Yield every 10 loops 69 else if (count % 10 == 0) { 70 71 // To yield, store the task continuation then restore 72 // the base continuation. 73 if (taskCont.Store(0) == 0) { 74 baseCont.Restore(1); 75 } 76 } 77 } 78 } 79 // When restored, 'Store' will return what was passed to Restore, in this case 1 so fall here. 80 else { 81 // Count the yields, then go back to the task. 82 ++yields; 83 taskCont.Restore(1); 84 } 85 86 Assert.AreEqual(9, yields); 87 } 88 89 90 public class MicroThread 91 { 92 Yield()93 public void Yield() 94 { 95 if (MyThread.Store(0) == 0) { 96 MainThread.Restore(1); 97 } 98 } 99 Resume()100 public void Resume() 101 { 102 if (MainThread.Store(0) == 0) { 103 MyThread.Restore(1); 104 } 105 } 106 DoWork(Action action)107 public void DoWork(Action action) 108 { 109 if (MainThread.Store(0) == 0) { 110 action(); 111 Done = true; 112 MainThread.Restore(1); 113 } 114 } 115 116 public bool Done = false; 117 public Continuation MainThread = new Continuation(); 118 public Continuation MyThread = new Continuation(); 119 } 120 121 public class MicroBJob 122 { 123 private int _Count = 0; 124 public int Count 125 { 126 get { return _Count; } 127 set { _Count = value; } 128 } 129 130 public MicroThread MicroThread; Work()131 public void Work() 132 { 133 while (Count < 100) { 134 ++Count; 135 if (Count % 10 == 0) { 136 MicroThread.Yield(); 137 } 138 } 139 } 140 } 141 142 [Test] MicroThreadTest()143 public void MicroThreadTest() 144 { 145 MicroThread microA = new MicroThread(); 146 MicroThread microB = new MicroThread(); 147 148 microA.MainThread.Mark(); 149 microA.MyThread.Mark(); 150 microB.MainThread.Mark(); 151 microB.MyThread.Mark(); 152 153 Assert.AreEqual(false, microA.Done); 154 Assert.AreEqual(false, microB.Done); 155 156 microA.DoWork(() => 157 { 158 int count = 0; 159 while (count < 100) { 160 ++count; 161 if (count % 10 == 0) { 162 microA.Yield(); 163 } 164 } 165 }); 166 167 MicroBJob jobB = new MicroBJob(); 168 jobB.MicroThread = microB; 169 170 microB.DoWork(jobB.Work); 171 172 Assert.AreEqual(false, microA.Done); 173 Assert.AreEqual(false, microB.Done); 174 175 int yields = 0; 176 while (yields < 20) { 177 if (!microA.Done) microA.Resume(); 178 if (!microB.Done) microB.Resume(); 179 if (microA.Done && microB.Done) break; 180 ++yields; 181 } 182 183 Assert.AreEqual(true, microA.Done); 184 Assert.AreEqual(true, microB.Done); 185 Assert.AreEqual(100, jobB.Count); 186 Assert.AreEqual(9, yields); 187 } 188 } 189 } 190