##// END OF EJS Templates
Added ResetState to RunnableComponent to reset in case of failure...
cin -
r205:8200ab154c8a v2
parent child
Show More
@@ -0,0 +1,4
1 <?xml version="1.0" encoding="utf-8"?>
2 <packages>
3 <package id="NUnit" version="2.6.4" targetFramework="net45" />
4 </packages> No newline at end of file
@@ -0,0 +1,16
1 using System;
2
3 namespace Implab.Components
4 {
5 public class StateChangeEventArgs {
6 /// <summary>
7 /// The error information if any
8 /// </summary>
9 public Exception LastError { get; set; }
10
11 /// <summary>
12 /// The state of the service corresponding to this event
13 /// </summary>
14 public ExecutionState State { get; set; }
15 }
16 }
@@ -1,863 +1,863
1 using System;
1 using System;
2 using System.Reflection;
2 using System.Reflection;
3 using System.Threading;
3 using System.Threading;
4 using Implab.Parallels;
4 using Implab.Parallels;
5
5
6 #if MONO
6 #if MONO
7
7
8 using NUnit.Framework;
8 using NUnit.Framework;
9 using TestClassAttribute = NUnit.Framework.TestFixtureAttribute;
9 using TestClassAttribute = NUnit.Framework.TestFixtureAttribute;
10 using TestMethodAttribute = NUnit.Framework.TestAttribute;
10 using TestMethodAttribute = NUnit.Framework.TestAttribute;
11
11
12 #else
12 #else
13
13
14 using Microsoft.VisualStudio.TestTools.UnitTesting;
14 using Microsoft.VisualStudio.TestTools.UnitTesting;
15
15
16 #endif
16 #endif
17
17
18 namespace Implab.Test {
18 namespace Implab.Test {
19 [TestClass]
19 [TestClass]
20 public class AsyncTests {
20 public class AsyncTests {
21 [TestMethod]
21 [TestMethod]
22 public void ResolveTest() {
22 public void ResolveTest() {
23 int res = -1;
23 int res = -1;
24 var p = new Promise<int>();
24 var p = new Promise<int>();
25 p.Then(x => res = x);
25 p.Then(x => res = x);
26 p.Resolve(100);
26 p.Resolve(100);
27
27
28 Assert.AreEqual(100, res);
28 Assert.AreEqual(100, res);
29 }
29 }
30
30
31 [TestMethod]
31 [TestMethod]
32 public void RejectTest() {
32 public void RejectTest() {
33 int res = -1;
33 int res = -1;
34 Exception err = null;
34 Exception err = null;
35
35
36 var p = new Promise<int>();
36 var p = new Promise<int>();
37 p.Then(
37 p.Then(
38 x => res = x,
38 x => res = x,
39 e => {
39 e => {
40 err = e;
40 err = e;
41 return -2;
41 return -2;
42 }
42 }
43 );
43 );
44 p.Reject(new ApplicationException("error"));
44 p.Reject(new ApplicationException("error"));
45
45
46 Assert.AreEqual(res, -1);
46 Assert.AreEqual(res, -1);
47 Assert.AreEqual(err.Message, "error");
47 Assert.AreEqual(err.Message, "error");
48
48
49 }
49 }
50
50
51 [TestMethod]
51 [TestMethod]
52 public void CancelExceptionTest() {
52 public void CancelExceptionTest() {
53 var p = new Promise<bool>();
53 var p = new Promise<bool>();
54 p.CancelOperation(null);
54 p.CancelOperation(null);
55
55
56 var p2 = p.Then(x => x, null, reason => {
56 var p2 = p.Then(x => x, null, reason => {
57 throw new ApplicationException("CANCELLED");
57 throw new ApplicationException("CANCELLED");
58 });
58 });
59
59
60 try {
60 try {
61 p2.Join();
61 p2.Join();
62 Assert.Fail();
62 Assert.Fail();
63 } catch (ApplicationException err) {
63 } catch (ApplicationException err) {
64 Assert.AreEqual("CANCELLED", err.InnerException.Message);
64 Assert.AreEqual("CANCELLED", err.InnerException.Message);
65 }
65 }
66
66
67 }
67 }
68
68
69 [TestMethod]
69 [TestMethod]
70 public void ContinueOnCancelTest() {
70 public void ContinueOnCancelTest() {
71 var p = new Promise<bool>();
71 var p = new Promise<bool>();
72 p.CancelOperation(null);
72 p.CancelOperation(null);
73
73
74 var p2 = p
74 var p2 = p
75 .Then(x => x, null, reason => {
75 .Then(x => x, null, reason => {
76 throw new ApplicationException("CANCELLED");
76 throw new ApplicationException("CANCELLED");
77 })
77 })
78 .Then(x => x, e => true);
78 .Then(x => x, e => true);
79
79
80 Assert.AreEqual(true, p2.Join());
80 Assert.AreEqual(true, p2.Join());
81 }
81 }
82
82
83 [TestMethod]
83 [TestMethod]
84 public void JoinSuccessTest() {
84 public void JoinSuccessTest() {
85 var p = new Promise<int>();
85 var p = new Promise<int>();
86 p.Resolve(100);
86 p.Resolve(100);
87 Assert.AreEqual(p.Join(), 100);
87 Assert.AreEqual(p.Join(), 100);
88 }
88 }
89
89
90 [TestMethod]
90 [TestMethod]
91 public void JoinFailTest() {
91 public void JoinFailTest() {
92 var p = new Promise<int>();
92 var p = new Promise<int>();
93 p.Reject(new ApplicationException("failed"));
93 p.Reject(new ApplicationException("failed"));
94
94
95 try {
95 try {
96 p.Join();
96 p.Join();
97 throw new ApplicationException("WRONG!");
97 throw new ApplicationException("WRONG!");
98 } catch (TargetInvocationException err) {
98 } catch (TargetInvocationException err) {
99 Assert.AreEqual(err.InnerException.Message, "failed");
99 Assert.AreEqual(err.InnerException.Message, "failed");
100 } catch {
100 } catch {
101 Assert.Fail("Got wrong excaption");
101 Assert.Fail("Got wrong excaption");
102 }
102 }
103 }
103 }
104
104
105 [TestMethod]
105 [TestMethod]
106 public void MapTest() {
106 public void MapTest() {
107 var p = new Promise<int>();
107 var p = new Promise<int>();
108
108
109 var p2 = p.Then(x => x.ToString());
109 var p2 = p.Then(x => x.ToString());
110 p.Resolve(100);
110 p.Resolve(100);
111
111
112 Assert.AreEqual(p2.Join(), "100");
112 Assert.AreEqual(p2.Join(), "100");
113 }
113 }
114
114
115 [TestMethod]
115 [TestMethod]
116 public void FixErrorTest() {
116 public void FixErrorTest() {
117 var p = new Promise<int>();
117 var p = new Promise<int>();
118
118
119 var p2 = p.Then(x => x, e => 101);
119 var p2 = p.Then(x => x, e => 101);
120
120
121 p.Reject(new Exception());
121 p.Reject(new Exception());
122
122
123 Assert.AreEqual(p2.Join(), 101);
123 Assert.AreEqual(p2.Join(), 101);
124 }
124 }
125
125
126 [TestMethod]
126 [TestMethod]
127 public void ChainTest() {
127 public void ChainTest() {
128 var p1 = new Promise<int>();
128 var p1 = new Promise<int>();
129
129
130 var p3 = p1.Chain(x => {
130 var p3 = p1.Chain(x => {
131 var p2 = new Promise<string>();
131 var p2 = new Promise<string>();
132 p2.Resolve(x.ToString());
132 p2.Resolve(x.ToString());
133 return p2;
133 return p2;
134 });
134 });
135
135
136 p1.Resolve(100);
136 p1.Resolve(100);
137
137
138 Assert.AreEqual(p3.Join(), "100");
138 Assert.AreEqual(p3.Join(), "100");
139 }
139 }
140
140
141 [TestMethod]
141 [TestMethod]
142 public void ChainFailTest() {
142 public void ChainFailTest() {
143 var p1 = new Promise<int>();
143 var p1 = new Promise<int>();
144
144
145 var p3 = p1.Chain(x => {
145 var p3 = p1.Chain(x => {
146 var p2 = new Promise<string>();
146 var p2 = new Promise<string>();
147 p2.Reject(new Exception("DIE!!!"));
147 p2.Reject(new Exception("DIE!!!"));
148 return p2;
148 return p2;
149 });
149 });
150
150
151 p1.Resolve(100);
151 p1.Resolve(100);
152
152
153 Assert.IsTrue(p3.IsResolved);
153 Assert.IsTrue(p3.IsResolved);
154 }
154 }
155
155
156 [TestMethod]
156 [TestMethod]
157 public void PoolTest() {
157 public void PoolTest() {
158 var pid = Thread.CurrentThread.ManagedThreadId;
158 var pid = Thread.CurrentThread.ManagedThreadId;
159 var p = AsyncPool.Invoke(() => Thread.CurrentThread.ManagedThreadId);
159 var p = AsyncPool.Invoke(() => Thread.CurrentThread.ManagedThreadId);
160
160
161 Assert.AreNotEqual(pid, p.Join());
161 Assert.AreNotEqual(pid, p.Join());
162 }
162 }
163
163
164 [TestMethod]
164 [TestMethod]
165 public void WorkerPoolSizeTest() {
165 public void WorkerPoolSizeTest() {
166 var pool = new WorkerPool(5, 10, 1);
166 var pool = new WorkerPool(5, 10, 1);
167
167
168 Assert.AreEqual(5, pool.PoolSize);
168 Assert.AreEqual(5, pool.PoolSize);
169
169
170 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
170 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
171 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
171 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
172 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
172 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
173
173
174 Assert.AreEqual(5, pool.PoolSize);
174 Assert.AreEqual(5, pool.PoolSize);
175
175
176 for (int i = 0; i < 100; i++)
176 for (int i = 0; i < 100; i++)
177 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
177 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
178 Thread.Sleep(200);
178 Thread.Sleep(200);
179 Assert.AreEqual(10, pool.PoolSize);
179 Assert.AreEqual(10, pool.PoolSize);
180
180
181 pool.Dispose();
181 pool.Dispose();
182 }
182 }
183
183
184 [TestMethod]
184 [TestMethod]
185 public void WorkerPoolCorrectTest() {
185 public void WorkerPoolCorrectTest() {
186 var pool = new WorkerPool(0,1000,100);
186 var pool = new WorkerPool(0,1000,100);
187
187
188 const int iterations = 1000;
188 const int iterations = 1000;
189 int pending = iterations;
189 int pending = iterations;
190 var stop = new ManualResetEvent(false);
190 var stop = new ManualResetEvent(false);
191
191
192 var count = 0;
192 var count = 0;
193 for (int i = 0; i < iterations; i++) {
193 for (int i = 0; i < iterations; i++) {
194 pool
194 pool
195 .Invoke(() => 1)
195 .Invoke(() => 1)
196 .Then(x => Interlocked.Add(ref count, x))
196 .Then(x => Interlocked.Add(ref count, x))
197 .Then(x => Math.Log10(x))
197 .Then(x => Math.Log10(x))
198 .On(() => {
198 .On(() => {
199 Interlocked.Decrement(ref pending);
199 Interlocked.Decrement(ref pending);
200 if (pending == 0)
200 if (pending == 0)
201 stop.Set();
201 stop.Set();
202 }, PromiseEventType.All);
202 }, PromiseEventType.All);
203 }
203 }
204
204
205 stop.WaitOne();
205 stop.WaitOne();
206
206
207 Assert.AreEqual(iterations, count);
207 Assert.AreEqual(iterations, count);
208 Console.WriteLine("Max threads: {0}", pool.MaxRunningThreads);
208 Console.WriteLine("Max threads: {0}", pool.MaxRunningThreads);
209 pool.Dispose();
209 pool.Dispose();
210
210
211 }
211 }
212
212
213 [TestMethod]
213 [TestMethod]
214 public void WorkerPoolDisposeTest() {
214 public void WorkerPoolDisposeTest() {
215 var pool = new WorkerPool(5, 20);
215 var pool = new WorkerPool(5, 20);
216 Assert.AreEqual(5, pool.PoolSize);
216 Assert.AreEqual(5, pool.PoolSize);
217 pool.Dispose();
217 pool.Dispose();
218 Thread.Sleep(500);
218 Thread.Sleep(500);
219 Assert.AreEqual(0, pool.PoolSize);
219 Assert.AreEqual(0, pool.PoolSize);
220 pool.Dispose();
220 pool.Dispose();
221 }
221 }
222
222
223 [TestMethod]
223 [TestMethod]
224 public void MTQueueTest() {
224 public void MTQueueTest() {
225 var queue = new MTQueue<int>();
225 var queue = new MTQueue<int>();
226 int res;
226 int res;
227
227
228 queue.Enqueue(10);
228 queue.Enqueue(10);
229 Assert.IsTrue(queue.TryDequeue(out res));
229 Assert.IsTrue(queue.TryDequeue(out res));
230 Assert.AreEqual(10, res);
230 Assert.AreEqual(10, res);
231 Assert.IsFalse(queue.TryDequeue(out res));
231 Assert.IsFalse(queue.TryDequeue(out res));
232
232
233 for (int i = 0; i < 1000; i++)
233 for (int i = 0; i < 1000; i++)
234 queue.Enqueue(i);
234 queue.Enqueue(i);
235
235
236 for (int i = 0; i < 1000; i++) {
236 for (int i = 0; i < 1000; i++) {
237 queue.TryDequeue(out res);
237 queue.TryDequeue(out res);
238 Assert.AreEqual(i, res);
238 Assert.AreEqual(i, res);
239 }
239 }
240
240
241 int writers = 0;
241 int writers = 0;
242 int readers = 0;
242 int readers = 0;
243 var stop = new ManualResetEvent(false);
243 var stop = new ManualResetEvent(false);
244 int total = 0;
244 int total = 0;
245
245
246 const int itemsPerWriter = 10000;
246 const int itemsPerWriter = 10000;
247 const int writersCount = 10;
247 const int writersCount = 10;
248
248
249 for (int i = 0; i < writersCount; i++) {
249 for (int i = 0; i < writersCount; i++) {
250 Interlocked.Increment(ref writers);
250 Interlocked.Increment(ref writers);
251 AsyncPool
251 AsyncPool
252 .RunThread(() => {
252 .RunThread(() => {
253 for (int ii = 0; ii < itemsPerWriter; ii++) {
253 for (int ii = 0; ii < itemsPerWriter; ii++) {
254 queue.Enqueue(1);
254 queue.Enqueue(1);
255 }
255 }
256 return 1;
256 return 1;
257 })
257 })
258 .On(() => Interlocked.Decrement(ref writers), PromiseEventType.All);
258 .On(() => Interlocked.Decrement(ref writers), PromiseEventType.All);
259 }
259 }
260
260
261 for (int i = 0; i < 10; i++) {
261 for (int i = 0; i < 10; i++) {
262 Interlocked.Increment(ref readers);
262 Interlocked.Increment(ref readers);
263 AsyncPool
263 AsyncPool
264 .RunThread(() => {
264 .RunThread(() => {
265 int t;
265 int t;
266 do {
266 do {
267 while (queue.TryDequeue(out t))
267 while (queue.TryDequeue(out t))
268 Interlocked.Add(ref total, t);
268 Interlocked.Add(ref total, t);
269 } while (writers > 0);
269 } while (writers > 0);
270 return 1;
270 return 1;
271 })
271 })
272 .On(() => {
272 .On(() => {
273 Interlocked.Decrement(ref readers);
273 Interlocked.Decrement(ref readers);
274 if (readers == 0)
274 if (readers == 0)
275 stop.Set();
275 stop.Set();
276 }, PromiseEventType.All);
276 }, PromiseEventType.All);
277 }
277 }
278
278
279 stop.WaitOne();
279 stop.WaitOne();
280
280
281 Assert.AreEqual(100000, total);
281 Assert.AreEqual(100000, total);
282 }
282 }
283
283
284 [TestMethod]
284 [TestMethod]
285 public void AsyncQueueTest() {
285 public void AsyncQueueTest() {
286 var queue = new AsyncQueue<int>();
286 var queue = new AsyncQueue<int>();
287 int res;
287 int res;
288
288
289 queue.Enqueue(10);
289 queue.Enqueue(10);
290 Assert.IsTrue(queue.TryDequeue(out res));
290 Assert.IsTrue(queue.TryDequeue(out res));
291 Assert.AreEqual(10, res);
291 Assert.AreEqual(10, res);
292 Assert.IsFalse(queue.TryDequeue(out res));
292 Assert.IsFalse(queue.TryDequeue(out res));
293
293
294 for (int i = 0; i < 1000; i++)
294 for (int i = 0; i < 1000; i++)
295 queue.Enqueue(i);
295 queue.Enqueue(i);
296
296
297 for (int i = 0; i < 1000; i++) {
297 for (int i = 0; i < 1000; i++) {
298 queue.TryDequeue(out res);
298 queue.TryDequeue(out res);
299 Assert.AreEqual(i, res);
299 Assert.AreEqual(i, res);
300 }
300 }
301
301
302 const int count = 10000000;
302 const int count = 10000000;
303
303
304 int res1 = 0, res2 = 0;
304 int res1 = 0, res2 = 0;
305 var t1 = Environment.TickCount;
305 var t1 = Environment.TickCount;
306
306
307 AsyncPool.RunThread(
307 AsyncPool.RunThread(
308 () => {
308 () => {
309 for (var i = 0; i < count; i++)
309 for (var i = 0; i < count; i++)
310 queue.Enqueue(1);
310 queue.Enqueue(1);
311 Console.WriteLine("done writer #1: {0} ms", Environment.TickCount - t1);
311 Console.WriteLine("done writer #1: {0} ms", Environment.TickCount - t1);
312 },
312 },
313 () => {
313 () => {
314 for (var i = 0; i < count; i++)
314 for (var i = 0; i < count; i++)
315 queue.Enqueue(2);
315 queue.Enqueue(2);
316 Console.WriteLine("done writer #2: {0} ms", Environment.TickCount - t1);
316 Console.WriteLine("done writer #2: {0} ms", Environment.TickCount - t1);
317 },
317 },
318 () => {
318 () => {
319 int temp;
319 int temp;
320 int i = 0;
320 int i = 0;
321 while (i < count)
321 while (i < count)
322 if (queue.TryDequeue(out temp)) {
322 if (queue.TryDequeue(out temp)) {
323 i++;
323 i++;
324 res1 += temp;
324 res1 += temp;
325 }
325 }
326 Console.WriteLine("done reader #1: {0} ms", Environment.TickCount - t1);
326 Console.WriteLine("done reader #1: {0} ms", Environment.TickCount - t1);
327 },
327 },
328 () => {
328 () => {
329 int temp;
329 int temp;
330 int i = 0;
330 int i = 0;
331 while (i < count)
331 while (i < count)
332 if (queue.TryDequeue(out temp)) {
332 if (queue.TryDequeue(out temp)) {
333 i++;
333 i++;
334 res2 += temp;
334 res2 += temp;
335 }
335 }
336 Console.WriteLine("done reader #2: {0} ms", Environment.TickCount - t1);
336 Console.WriteLine("done reader #2: {0} ms", Environment.TickCount - t1);
337 }
337 }
338 )
338 )
339 .Bundle()
339 .PromiseAll()
340 .Join();
340 .Join();
341
341
342 Assert.AreEqual(count * 3, res1 + res2);
342 Assert.AreEqual(count * 3, res1 + res2);
343
343
344 Console.WriteLine(
344 Console.WriteLine(
345 "done: {0} ms, summ#1: {1}, summ#2: {2}, total: {3}, count: {4}",
345 "done: {0} ms, summ#1: {1}, summ#2: {2}, total: {3}, count: {4}",
346 Environment.TickCount - t1,
346 Environment.TickCount - t1,
347 res1,
347 res1,
348 res2,
348 res2,
349 res1 + res2,
349 res1 + res2,
350 count
350 count
351 );
351 );
352 }
352 }
353
353
354 [TestMethod]
354 [TestMethod]
355 public void AsyncQueueBatchTest() {
355 public void AsyncQueueBatchTest() {
356 var queue = new AsyncQueue<int>();
356 var queue = new AsyncQueue<int>();
357
357
358 const int wBatch = 29;
358 const int wBatch = 29;
359 const int wCount = 400000;
359 const int wCount = 400000;
360 const int total = wBatch * wCount * 2;
360 const int total = wBatch * wCount * 2;
361 const int summ = wBatch * wCount * 3;
361 const int summ = wBatch * wCount * 3;
362
362
363 int r1 = 0, r2 = 0;
363 int r1 = 0, r2 = 0;
364 const int rBatch = 111;
364 const int rBatch = 111;
365 int read = 0;
365 int read = 0;
366
366
367 var t1 = Environment.TickCount;
367 var t1 = Environment.TickCount;
368
368
369 AsyncPool.RunThread(
369 AsyncPool.RunThread(
370 () => {
370 () => {
371 var buffer = new int[wBatch];
371 var buffer = new int[wBatch];
372 for(int i = 0; i<wBatch; i++)
372 for(int i = 0; i<wBatch; i++)
373 buffer[i] = 1;
373 buffer[i] = 1;
374
374
375 for(int i =0; i < wCount; i++)
375 for(int i =0; i < wCount; i++)
376 queue.EnqueueRange(buffer,0,wBatch);
376 queue.EnqueueRange(buffer,0,wBatch);
377 Console.WriteLine("done writer #1: {0} ms", Environment.TickCount - t1);
377 Console.WriteLine("done writer #1: {0} ms", Environment.TickCount - t1);
378 },
378 },
379 () => {
379 () => {
380 var buffer = new int[wBatch];
380 var buffer = new int[wBatch];
381 for(int i = 0; i<wBatch; i++)
381 for(int i = 0; i<wBatch; i++)
382 buffer[i] = 2;
382 buffer[i] = 2;
383
383
384 for(int i =0; i < wCount; i++)
384 for(int i =0; i < wCount; i++)
385 queue.EnqueueRange(buffer,0,wBatch);
385 queue.EnqueueRange(buffer,0,wBatch);
386 Console.WriteLine("done writer #2: {0} ms", Environment.TickCount - t1);
386 Console.WriteLine("done writer #2: {0} ms", Environment.TickCount - t1);
387 },
387 },
388 () => {
388 () => {
389 var buffer = new int[rBatch];
389 var buffer = new int[rBatch];
390
390
391 while(read < total) {
391 while(read < total) {
392 int actual;
392 int actual;
393 if (queue.TryDequeueRange(buffer,0,rBatch,out actual)) {
393 if (queue.TryDequeueRange(buffer,0,rBatch,out actual)) {
394 for(int i=0; i< actual; i++)
394 for(int i=0; i< actual; i++)
395 r1 += buffer[i];
395 r1 += buffer[i];
396 Interlocked.Add(ref read, actual);
396 Interlocked.Add(ref read, actual);
397 }
397 }
398 }
398 }
399
399
400 Console.WriteLine("done reader #1: {0} ms", Environment.TickCount - t1);
400 Console.WriteLine("done reader #1: {0} ms", Environment.TickCount - t1);
401 },
401 },
402 () => {
402 () => {
403 var buffer = new int[rBatch];
403 var buffer = new int[rBatch];
404
404
405 while(read < total) {
405 while(read < total) {
406 int actual;
406 int actual;
407 if (queue.TryDequeueRange(buffer,0,rBatch,out actual)) {
407 if (queue.TryDequeueRange(buffer,0,rBatch,out actual)) {
408 for(int i=0; i< actual; i++)
408 for(int i=0; i< actual; i++)
409 r2 += buffer[i];
409 r2 += buffer[i];
410 Interlocked.Add(ref read, actual);
410 Interlocked.Add(ref read, actual);
411 }
411 }
412 }
412 }
413
413
414 Console.WriteLine("done reader #2: {0} ms", Environment.TickCount - t1);
414 Console.WriteLine("done reader #2: {0} ms", Environment.TickCount - t1);
415 }
415 }
416 )
416 )
417 .Bundle()
417 .PromiseAll()
418 .Join();
418 .Join();
419
419
420 Assert.AreEqual(summ , r1 + r2);
420 Assert.AreEqual(summ , r1 + r2);
421
421
422 Console.WriteLine(
422 Console.WriteLine(
423 "done: {0} ms, summ#1: {1}, summ#2: {2}, total: {3}, count: {4}",
423 "done: {0} ms, summ#1: {1}, summ#2: {2}, total: {3}, count: {4}",
424 Environment.TickCount - t1,
424 Environment.TickCount - t1,
425 r1,
425 r1,
426 r2,
426 r2,
427 r1 + r2,
427 r1 + r2,
428 total
428 total
429 );
429 );
430 }
430 }
431
431
432 [TestMethod]
432 [TestMethod]
433 public void AsyncQueueChunkDequeueTest() {
433 public void AsyncQueueChunkDequeueTest() {
434 var queue = new AsyncQueue<int>();
434 var queue = new AsyncQueue<int>();
435
435
436 const int wBatch = 31;
436 const int wBatch = 31;
437 const int wCount = 200000;
437 const int wCount = 200000;
438 const int total = wBatch * wCount * 3;
438 const int total = wBatch * wCount * 3;
439 const int summ = wBatch * wCount * 6;
439 const int summ = wBatch * wCount * 6;
440
440
441 int r1 = 0, r2 = 0;
441 int r1 = 0, r2 = 0;
442 const int rBatch = 1024;
442 const int rBatch = 1024;
443 int read = 0;
443 int read = 0;
444
444
445 var t1 = Environment.TickCount;
445 var t1 = Environment.TickCount;
446
446
447 AsyncPool.RunThread(
447 AsyncPool.RunThread(
448 () => {
448 () => {
449 var buffer = new int[wBatch];
449 var buffer = new int[wBatch];
450 for(int i = 0; i<wBatch; i++)
450 for(int i = 0; i<wBatch; i++)
451 buffer[i] = 1;
451 buffer[i] = 1;
452
452
453 for(int i =0; i < wCount; i++)
453 for(int i =0; i < wCount; i++)
454 queue.EnqueueRange(buffer,0,wBatch);
454 queue.EnqueueRange(buffer,0,wBatch);
455 Console.WriteLine("done writer #1: {0} ms", Environment.TickCount - t1);
455 Console.WriteLine("done writer #1: {0} ms", Environment.TickCount - t1);
456 },
456 },
457 () => {
457 () => {
458 var buffer = new int[wBatch];
458 var buffer = new int[wBatch];
459 for(int i = 0; i<wBatch; i++)
459 for(int i = 0; i<wBatch; i++)
460 buffer[i] = 2;
460 buffer[i] = 2;
461
461
462 for(int i =0; i < wCount; i++)
462 for(int i =0; i < wCount; i++)
463 queue.EnqueueRange(buffer,0,wBatch);
463 queue.EnqueueRange(buffer,0,wBatch);
464 Console.WriteLine("done writer #2: {0} ms", Environment.TickCount - t1);
464 Console.WriteLine("done writer #2: {0} ms", Environment.TickCount - t1);
465 },
465 },
466 () => {
466 () => {
467 var buffer = new int[wBatch];
467 var buffer = new int[wBatch];
468 for(int i = 0; i<wBatch; i++)
468 for(int i = 0; i<wBatch; i++)
469 buffer[i] = 3;
469 buffer[i] = 3;
470
470
471 for(int i =0; i < wCount; i++)
471 for(int i =0; i < wCount; i++)
472 queue.EnqueueRange(buffer,0,wBatch);
472 queue.EnqueueRange(buffer,0,wBatch);
473 Console.WriteLine("done writer #3: {0} ms", Environment.TickCount - t1);
473 Console.WriteLine("done writer #3: {0} ms", Environment.TickCount - t1);
474 },
474 },
475 () => {
475 () => {
476 var buffer = new int[rBatch];
476 var buffer = new int[rBatch];
477 int count = 1;
477 int count = 1;
478 double avgchunk = 0;
478 double avgchunk = 0;
479 while(read < total) {
479 while(read < total) {
480 int actual;
480 int actual;
481 if (queue.TryDequeueChunk(buffer,0,rBatch,out actual)) {
481 if (queue.TryDequeueChunk(buffer,0,rBatch,out actual)) {
482 for(int i=0; i< actual; i++)
482 for(int i=0; i< actual; i++)
483 r2 += buffer[i];
483 r2 += buffer[i];
484 Interlocked.Add(ref read, actual);
484 Interlocked.Add(ref read, actual);
485 avgchunk = avgchunk*(count-1)/count + actual/(double)count;
485 avgchunk = avgchunk*(count-1)/count + actual/(double)count;
486 count ++;
486 count ++;
487 }
487 }
488 }
488 }
489
489
490 Console.WriteLine("done reader #2: {0} ms, avg chunk size: {1}", Environment.TickCount - t1, avgchunk);
490 Console.WriteLine("done reader #2: {0} ms, avg chunk size: {1}", Environment.TickCount - t1, avgchunk);
491 }
491 }
492 )
492 )
493 .Bundle()
493 .PromiseAll()
494 .Join();
494 .Join();
495
495
496 Assert.AreEqual(summ , r1 + r2);
496 Assert.AreEqual(summ , r1 + r2);
497
497
498 Console.WriteLine(
498 Console.WriteLine(
499 "done: {0} ms, summ#1: {1}, summ#2: {2}, total: {3}, count: {4}",
499 "done: {0} ms, summ#1: {1}, summ#2: {2}, total: {3}, count: {4}",
500 Environment.TickCount - t1,
500 Environment.TickCount - t1,
501 r1,
501 r1,
502 r2,
502 r2,
503 r1 + r2,
503 r1 + r2,
504 total
504 total
505 );
505 );
506 }
506 }
507
507
508 [TestMethod]
508 [TestMethod]
509 public void AsyncQueueDrainTest() {
509 public void AsyncQueueDrainTest() {
510 var queue = new AsyncQueue<int>();
510 var queue = new AsyncQueue<int>();
511
511
512 const int wBatch = 11;
512 const int wBatch = 11;
513 const int wCount = 200000;
513 const int wCount = 200000;
514 const int total = wBatch * wCount * 3;
514 const int total = wBatch * wCount * 3;
515 const int summ = wBatch * wCount * 3;
515 const int summ = wBatch * wCount * 3;
516
516
517 int r1 = 0, r2 = 0;
517 int r1 = 0, r2 = 0;
518 const int rBatch = 11;
518 const int rBatch = 11;
519 int read = 0;
519 int read = 0;
520
520
521 var t1 = Environment.TickCount;
521 var t1 = Environment.TickCount;
522
522
523 AsyncPool.RunThread(
523 AsyncPool.RunThread(
524 () => {
524 () => {
525 var buffer = new int[wBatch];
525 var buffer = new int[wBatch];
526 for(int i = 0; i<wBatch; i++)
526 for(int i = 0; i<wBatch; i++)
527 buffer[i] = 1;
527 buffer[i] = 1;
528
528
529 for(int i =0; i < wCount; i++)
529 for(int i =0; i < wCount; i++)
530 queue.EnqueueRange(buffer,0,wBatch);
530 queue.EnqueueRange(buffer,0,wBatch);
531 Console.WriteLine("done writer #1: {0} ms", Environment.TickCount - t1);
531 Console.WriteLine("done writer #1: {0} ms", Environment.TickCount - t1);
532 },
532 },
533 () => {
533 () => {
534 for(int i =0; i < wCount * wBatch; i++)
534 for(int i =0; i < wCount * wBatch; i++)
535 queue.Enqueue(1);
535 queue.Enqueue(1);
536 Console.WriteLine("done writer #2: {0} ms", Environment.TickCount - t1);
536 Console.WriteLine("done writer #2: {0} ms", Environment.TickCount - t1);
537 },
537 },
538 () => {
538 () => {
539 var buffer = new int[wBatch];
539 var buffer = new int[wBatch];
540 for(int i = 0; i<wBatch; i++)
540 for(int i = 0; i<wBatch; i++)
541 buffer[i] = 1;
541 buffer[i] = 1;
542
542
543 for(int i =0; i < wCount; i++)
543 for(int i =0; i < wCount; i++)
544 queue.EnqueueRange(buffer,0,wBatch);
544 queue.EnqueueRange(buffer,0,wBatch);
545 Console.WriteLine("done writer #3: {0} ms", Environment.TickCount - t1);
545 Console.WriteLine("done writer #3: {0} ms", Environment.TickCount - t1);
546 },
546 },
547 /*() => {
547 /*() => {
548 int temp;
548 int temp;
549 int count = 0;
549 int count = 0;
550 while (read < total)
550 while (read < total)
551 if (queue.TryDequeue(out temp)) {
551 if (queue.TryDequeue(out temp)) {
552 count++;
552 count++;
553 r1 += temp;
553 r1 += temp;
554 Interlocked.Increment(ref read);
554 Interlocked.Increment(ref read);
555 }
555 }
556 Console.WriteLine("done reader #1: {0} ms, {1} count", Environment.TickCount - t1, count);
556 Console.WriteLine("done reader #1: {0} ms, {1} count", Environment.TickCount - t1, count);
557 },*/
557 },*/
558 /*() => {
558 /*() => {
559 var buffer = new int[rBatch];
559 var buffer = new int[rBatch];
560 var count = 0;
560 var count = 0;
561 while(read < total) {
561 while(read < total) {
562 int actual;
562 int actual;
563 if (queue.TryDequeueRange(buffer,0,rBatch,out actual)) {
563 if (queue.TryDequeueRange(buffer,0,rBatch,out actual)) {
564 for(int i=0; i< actual; i++)
564 for(int i=0; i< actual; i++)
565 r1 += buffer[i];
565 r1 += buffer[i];
566 Interlocked.Add(ref read, actual);
566 Interlocked.Add(ref read, actual);
567 count += actual;
567 count += actual;
568 }
568 }
569 }
569 }
570
570
571 Console.WriteLine("done reader #1: {0} ms, {1} items", Environment.TickCount - t1, count);
571 Console.WriteLine("done reader #1: {0} ms, {1} items", Environment.TickCount - t1, count);
572 },*/
572 },*/
573 () => {
573 () => {
574 var count = 0;
574 var count = 0;
575 while(read < total) {
575 while(read < total) {
576 var buffer = queue.Drain();
576 var buffer = queue.Drain();
577 for(int i=0; i< buffer.Length; i++)
577 for(int i=0; i< buffer.Length; i++)
578 r1 += buffer[i];
578 r1 += buffer[i];
579 Interlocked.Add(ref read, buffer.Length);
579 Interlocked.Add(ref read, buffer.Length);
580 count += buffer.Length;
580 count += buffer.Length;
581 }
581 }
582 Console.WriteLine("done reader #1: {0} ms, {1} items", Environment.TickCount - t1, count);
582 Console.WriteLine("done reader #1: {0} ms, {1} items", Environment.TickCount - t1, count);
583 },
583 },
584 () => {
584 () => {
585 var count = 0;
585 var count = 0;
586 while(read < total) {
586 while(read < total) {
587 var buffer = queue.Drain();
587 var buffer = queue.Drain();
588 for(int i=0; i< buffer.Length; i++)
588 for(int i=0; i< buffer.Length; i++)
589 r2 += buffer[i];
589 r2 += buffer[i];
590 Interlocked.Add(ref read, buffer.Length);
590 Interlocked.Add(ref read, buffer.Length);
591 count += buffer.Length;
591 count += buffer.Length;
592 }
592 }
593 Console.WriteLine("done reader #2: {0} ms, {1} items", Environment.TickCount - t1, count);
593 Console.WriteLine("done reader #2: {0} ms, {1} items", Environment.TickCount - t1, count);
594 }
594 }
595 )
595 )
596 .Bundle()
596 .PromiseAll()
597 .Join();
597 .Join();
598
598
599 Assert.AreEqual(summ , r1 + r2);
599 Assert.AreEqual(summ , r1 + r2);
600
600
601 Console.WriteLine(
601 Console.WriteLine(
602 "done: {0} ms, summ#1: {1}, summ#2: {2}, total: {3}, count: {4}",
602 "done: {0} ms, summ#1: {1}, summ#2: {2}, total: {3}, count: {4}",
603 Environment.TickCount - t1,
603 Environment.TickCount - t1,
604 r1,
604 r1,
605 r2,
605 r2,
606 r1 + r2,
606 r1 + r2,
607 total
607 total
608 );
608 );
609 }
609 }
610
610
611 [TestMethod]
611 [TestMethod]
612 public void ParallelMapTest() {
612 public void ParallelMapTest() {
613
613
614 const int count = 100000;
614 const int count = 100000;
615
615
616 var args = new double[count];
616 var args = new double[count];
617 var rand = new Random();
617 var rand = new Random();
618
618
619 for (int i = 0; i < count; i++)
619 for (int i = 0; i < count; i++)
620 args[i] = rand.NextDouble();
620 args[i] = rand.NextDouble();
621
621
622 var t = Environment.TickCount;
622 var t = Environment.TickCount;
623 var res = args.ParallelMap(x => Math.Sin(x*x), 4).Join();
623 var res = args.ParallelMap(x => Math.Sin(x*x), 4).Join();
624
624
625 Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t);
625 Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t);
626
626
627 t = Environment.TickCount;
627 t = Environment.TickCount;
628 for (int i = 0; i < count; i++)
628 for (int i = 0; i < count; i++)
629 Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]);
629 Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]);
630 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
630 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
631 }
631 }
632
632
633 [TestMethod]
633 [TestMethod]
634 public void ChainedMapTest() {
634 public void ChainedMapTest() {
635
635
636 using (var pool = new WorkerPool()) {
636 using (var pool = new WorkerPool()) {
637 const int count = 10000;
637 const int count = 10000;
638
638
639 var args = new double[count];
639 var args = new double[count];
640 var rand = new Random();
640 var rand = new Random();
641
641
642 for (int i = 0; i < count; i++)
642 for (int i = 0; i < count; i++)
643 args[i] = rand.NextDouble();
643 args[i] = rand.NextDouble();
644
644
645 var t = Environment.TickCount;
645 var t = Environment.TickCount;
646 var res = args
646 var res = args
647 .ChainedMap(
647 .ChainedMap(
648 // Analysis disable once AccessToDisposedClosure
648 // Analysis disable once AccessToDisposedClosure
649 x => pool.Invoke(
649 x => pool.Invoke(
650 () => Math.Sin(x * x)
650 () => Math.Sin(x * x)
651 ),
651 ),
652 4
652 4
653 )
653 )
654 .Join();
654 .Join();
655
655
656 Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t);
656 Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t);
657
657
658 t = Environment.TickCount;
658 t = Environment.TickCount;
659 for (int i = 0; i < count; i++)
659 for (int i = 0; i < count; i++)
660 Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]);
660 Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]);
661 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
661 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
662 Console.WriteLine("Max workers: {0}", pool.MaxRunningThreads);
662 Console.WriteLine("Max workers: {0}", pool.MaxRunningThreads);
663 }
663 }
664 }
664 }
665
665
666 [TestMethod]
666 [TestMethod]
667 public void ParallelForEachTest() {
667 public void ParallelForEachTest() {
668
668
669 const int count = 100000;
669 const int count = 100000;
670
670
671 var args = new int[count];
671 var args = new int[count];
672 var rand = new Random();
672 var rand = new Random();
673
673
674 for (int i = 0; i < count; i++)
674 for (int i = 0; i < count; i++)
675 args[i] = (int)(rand.NextDouble() * 100);
675 args[i] = (int)(rand.NextDouble() * 100);
676
676
677 int result = 0;
677 int result = 0;
678
678
679 var t = Environment.TickCount;
679 var t = Environment.TickCount;
680 args.ParallelForEach(x => Interlocked.Add(ref result, x), 4).Join();
680 args.ParallelForEach(x => Interlocked.Add(ref result, x), 4).Join();
681
681
682 Console.WriteLine("Iteration complete in {0} ms, result: {1}", Environment.TickCount - t, result);
682 Console.WriteLine("Iteration complete in {0} ms, result: {1}", Environment.TickCount - t, result);
683
683
684 int result2 = 0;
684 int result2 = 0;
685
685
686 t = Environment.TickCount;
686 t = Environment.TickCount;
687 for (int i = 0; i < count; i++)
687 for (int i = 0; i < count; i++)
688 result2 += args[i];
688 result2 += args[i];
689 Assert.AreEqual(result2, result);
689 Assert.AreEqual(result2, result);
690 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
690 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
691 }
691 }
692
692
693 [TestMethod]
693 [TestMethod]
694 public void ComplexCase1Test() {
694 public void ComplexCase1Test() {
695 var flags = new bool[3];
695 var flags = new bool[3];
696
696
697 // op1 (aync 200ms) => op2 (async 200ms) => op3 (sync map)
697 // op1 (aync 200ms) => op2 (async 200ms) => op3 (sync map)
698
698
699 var step1 = PromiseHelper
699 var step1 = PromiseHelper
700 .Sleep(200, "Alan")
700 .Sleep(200, "Alan")
701 .On(() => flags[0] = true, PromiseEventType.Cancelled);
701 .On(() => flags[0] = true, PromiseEventType.Cancelled);
702 var p = step1
702 var p = step1
703 .Chain(x =>
703 .Chain(x =>
704 PromiseHelper
704 PromiseHelper
705 .Sleep(200, "Hi, " + x)
705 .Sleep(200, "Hi, " + x)
706 .Then(y => y)
706 .Then(y => y)
707 .On(() => flags[1] = true, PromiseEventType.Cancelled)
707 .On(() => flags[1] = true, PromiseEventType.Cancelled)
708 )
708 )
709 .On(() => flags[2] = true, PromiseEventType.Cancelled);
709 .On(() => flags[2] = true, PromiseEventType.Cancelled);
710 step1.Join();
710 step1.Join();
711 p.Cancel();
711 p.Cancel();
712 try {
712 try {
713 Assert.AreEqual(p.Join(), "Hi, Alan");
713 Assert.AreEqual(p.Join(), "Hi, Alan");
714 Assert.Fail("Shouldn't get here");
714 Assert.Fail("Shouldn't get here");
715 } catch (OperationCanceledException) {
715 } catch (OperationCanceledException) {
716 }
716 }
717
717
718 Assert.IsFalse(flags[0]);
718 Assert.IsFalse(flags[0]);
719 Assert.IsTrue(flags[1]);
719 Assert.IsTrue(flags[1]);
720 Assert.IsTrue(flags[2]);
720 Assert.IsTrue(flags[2]);
721 }
721 }
722
722
723 [TestMethod]
723 [TestMethod]
724 public void ChainedCancel1Test() {
724 public void ChainedCancel1Test() {
725 // при отмене сцепленной асинхронной операции все обещание должно
725 // при отмене сцепленной асинхронной операции все обещание должно
726 // завершаться ошибкой OperationCanceledException
726 // завершаться ошибкой OperationCanceledException
727 var p = PromiseHelper
727 var p = PromiseHelper
728 .Sleep(1, "Hi, HAL!")
728 .Sleep(1, "Hi, HAL!")
729 .Then(x => {
729 .Then(x => {
730 // запускаем две асинхронные операции
730 // запускаем две асинхронные операции
731 var result = PromiseHelper.Sleep(1000, "HEM ENABLED!!!");
731 var result = PromiseHelper.Sleep(1000, "HEM ENABLED!!!");
732 // вторая операция отменяет первую до завершения
732 // вторая операция отменяет первую до завершения
733 PromiseHelper
733 PromiseHelper
734 .Sleep(100, "HAL, STOP!")
734 .Sleep(100, "HAL, STOP!")
735 .Then(result.Cancel);
735 .Then(result.Cancel);
736 return result;
736 return result;
737 });
737 });
738 try {
738 try {
739 p.Join();
739 p.Join();
740 } catch (TargetInvocationException err) {
740 } catch (TargetInvocationException err) {
741 Assert.IsTrue(err.InnerException is OperationCanceledException);
741 Assert.IsTrue(err.InnerException is OperationCanceledException);
742 }
742 }
743 }
743 }
744
744
745 [TestMethod]
745 [TestMethod]
746 public void ChainedCancel2Test() {
746 public void ChainedCancel2Test() {
747 // при отмене цепочки обещаний, вложенные операции также должны отменяться
747 // при отмене цепочки обещаний, вложенные операции также должны отменяться
748 var pSurvive = new Promise<bool>();
748 var pSurvive = new Promise<bool>();
749 var hemStarted = new Signal();
749 var hemStarted = new Signal();
750 var p = PromiseHelper
750 var p = PromiseHelper
751 .Sleep(1, "Hi, HAL!")
751 .Sleep(1, "Hi, HAL!")
752 .Chain(() => {
752 .Chain(() => {
753 hemStarted.Set();
753 hemStarted.Set();
754 // запускаем две асинхронные операции
754 // запускаем две асинхронные операции
755 var result = PromiseHelper
755 var result = PromiseHelper
756 .Sleep(2000, "HEM ENABLED!!!")
756 .Sleep(2000, "HEM ENABLED!!!")
757 .Then(() => pSurvive.Resolve(false));
757 .Then(() => pSurvive.Resolve(false));
758
758
759 result
759 result
760 .On(() => pSurvive.Resolve(true), PromiseEventType.Cancelled);
760 .On(() => pSurvive.Resolve(true), PromiseEventType.Cancelled);
761
761
762 return result;
762 return result;
763 });
763 });
764
764
765 hemStarted.Wait();
765 hemStarted.Wait();
766 p.Cancel();
766 p.Cancel();
767
767
768 try {
768 try {
769 p.Join();
769 p.Join();
770 Assert.Fail();
770 Assert.Fail();
771 } catch (OperationCanceledException) {
771 } catch (OperationCanceledException) {
772 }
772 }
773 Assert.IsTrue(pSurvive.Join());
773 Assert.IsTrue(pSurvive.Join());
774 }
774 }
775
775
776 [TestMethod]
776 [TestMethod]
777 public void SharedLockTest() {
777 public void SharedLockTest() {
778 var l = new SharedLock();
778 var l = new SharedLock();
779 int shared = 0;
779 int shared = 0;
780 int exclusive = 0;
780 int exclusive = 0;
781 var s1 = new Signal();
781 var s1 = new Signal();
782 var log = new AsyncQueue<string>();
782 var log = new AsyncQueue<string>();
783
783
784 try {
784 try {
785 AsyncPool.RunThread(
785 AsyncPool.RunThread(
786 () => {
786 () => {
787 log.Enqueue("Reader #1 started");
787 log.Enqueue("Reader #1 started");
788 try {
788 try {
789 l.LockShared();
789 l.LockShared();
790 log.Enqueue("Reader #1 lock got");
790 log.Enqueue("Reader #1 lock got");
791 if (Interlocked.Increment(ref shared) == 2)
791 if (Interlocked.Increment(ref shared) == 2)
792 s1.Set();
792 s1.Set();
793 s1.Wait();
793 s1.Wait();
794 log.Enqueue("Reader #1 finished");
794 log.Enqueue("Reader #1 finished");
795 Interlocked.Decrement(ref shared);
795 Interlocked.Decrement(ref shared);
796 } finally {
796 } finally {
797 l.Release();
797 l.Release();
798 log.Enqueue("Reader #1 lock released");
798 log.Enqueue("Reader #1 lock released");
799 }
799 }
800 },
800 },
801 () => {
801 () => {
802 log.Enqueue("Reader #2 started");
802 log.Enqueue("Reader #2 started");
803
803
804 try {
804 try {
805 l.LockShared();
805 l.LockShared();
806 log.Enqueue("Reader #2 lock got");
806 log.Enqueue("Reader #2 lock got");
807
807
808 if (Interlocked.Increment(ref shared) == 2)
808 if (Interlocked.Increment(ref shared) == 2)
809 s1.Set();
809 s1.Set();
810 s1.Wait();
810 s1.Wait();
811 log.Enqueue("Reader #2 upgrading to writer");
811 log.Enqueue("Reader #2 upgrading to writer");
812 Interlocked.Decrement(ref shared);
812 Interlocked.Decrement(ref shared);
813 l.Upgrade();
813 l.Upgrade();
814 log.Enqueue("Reader #2 upgraded");
814 log.Enqueue("Reader #2 upgraded");
815
815
816 Assert.AreEqual(1, Interlocked.Increment(ref exclusive));
816 Assert.AreEqual(1, Interlocked.Increment(ref exclusive));
817 Assert.AreEqual(0, shared);
817 Assert.AreEqual(0, shared);
818 log.Enqueue("Reader #2 finished");
818 log.Enqueue("Reader #2 finished");
819 Interlocked.Decrement(ref exclusive);
819 Interlocked.Decrement(ref exclusive);
820 } finally {
820 } finally {
821 l.Release();
821 l.Release();
822 log.Enqueue("Reader #2 lock released");
822 log.Enqueue("Reader #2 lock released");
823 }
823 }
824 },
824 },
825 () => {
825 () => {
826 log.Enqueue("Writer #1 started");
826 log.Enqueue("Writer #1 started");
827 try {
827 try {
828 l.LockExclusive();
828 l.LockExclusive();
829 log.Enqueue("Writer #1 got the lock");
829 log.Enqueue("Writer #1 got the lock");
830 Assert.AreEqual(1, Interlocked.Increment(ref exclusive));
830 Assert.AreEqual(1, Interlocked.Increment(ref exclusive));
831 Interlocked.Decrement(ref exclusive);
831 Interlocked.Decrement(ref exclusive);
832 log.Enqueue("Writer #1 is finished");
832 log.Enqueue("Writer #1 is finished");
833 } finally {
833 } finally {
834 l.Release();
834 l.Release();
835 log.Enqueue("Writer #1 lock released");
835 log.Enqueue("Writer #1 lock released");
836 }
836 }
837 }
837 }
838 ).Bundle().Join(1000);
838 ).PromiseAll().Join(1000);
839 log.Enqueue("Done");
839 log.Enqueue("Done");
840 } catch(Exception error) {
840 } catch(Exception error) {
841 log.Enqueue(error.Message);
841 log.Enqueue(error.Message);
842 throw;
842 throw;
843 } finally {
843 } finally {
844 foreach (var m in log)
844 foreach (var m in log)
845 Console.WriteLine(m);
845 Console.WriteLine(m);
846 }
846 }
847 }
847 }
848
848
849 #if NET_4_5
849 #if NET_4_5
850
850
851 [TestMethod]
851 [TestMethod]
852 public async void TaskInteropTest() {
852 public async void TaskInteropTest() {
853 var promise = new Promise<int>();
853 var promise = new Promise<int>();
854 promise.Resolve(10);
854 promise.Resolve(10);
855 var res = await promise;
855 var res = await promise;
856
856
857 Assert.AreEqual(10, res);
857 Assert.AreEqual(10, res);
858 }
858 }
859
859
860 #endif
860 #endif
861 }
861 }
862 }
862 }
863
863
@@ -1,52 +1,55
1 <?xml version="1.0" encoding="utf-8"?>
1 <?xml version="1.0" encoding="utf-8"?>
2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <PropertyGroup>
3 <PropertyGroup>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6 <ProductVersion>8.0.30703</ProductVersion>
6 <ProductVersion>8.0.30703</ProductVersion>
7 <SchemaVersion>2.0</SchemaVersion>
7 <SchemaVersion>2.0</SchemaVersion>
8 <ProjectGuid>{4D364996-7ECD-4193-8F90-F223FFEA49DA}</ProjectGuid>
8 <ProjectGuid>{4D364996-7ECD-4193-8F90-F223FFEA49DA}</ProjectGuid>
9 <OutputType>Library</OutputType>
9 <OutputType>Library</OutputType>
10 <RootNamespace>Implab.Format.Test</RootNamespace>
10 <RootNamespace>Implab.Format.Test</RootNamespace>
11 <AssemblyName>Implab.Format.Test</AssemblyName>
11 <AssemblyName>Implab.Format.Test</AssemblyName>
12 <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
12 <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
13 <ReleaseVersion>0.2</ReleaseVersion>
13 <ReleaseVersion>0.2</ReleaseVersion>
14 </PropertyGroup>
14 </PropertyGroup>
15 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
15 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
16 <DebugSymbols>true</DebugSymbols>
16 <DebugSymbols>true</DebugSymbols>
17 <DebugType>full</DebugType>
17 <DebugType>full</DebugType>
18 <Optimize>false</Optimize>
18 <Optimize>false</Optimize>
19 <OutputPath>bin\Debug</OutputPath>
19 <OutputPath>bin\Debug</OutputPath>
20 <DefineConstants>DEBUG;</DefineConstants>
20 <DefineConstants>DEBUG;</DefineConstants>
21 <ErrorReport>prompt</ErrorReport>
21 <ErrorReport>prompt</ErrorReport>
22 <WarningLevel>4</WarningLevel>
22 <WarningLevel>4</WarningLevel>
23 <ConsolePause>false</ConsolePause>
23 <ConsolePause>false</ConsolePause>
24 </PropertyGroup>
24 </PropertyGroup>
25 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
25 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
26 <DebugType>full</DebugType>
26 <DebugType>full</DebugType>
27 <Optimize>true</Optimize>
27 <Optimize>true</Optimize>
28 <OutputPath>bin\Release</OutputPath>
28 <OutputPath>bin\Release</OutputPath>
29 <ErrorReport>prompt</ErrorReport>
29 <ErrorReport>prompt</ErrorReport>
30 <WarningLevel>4</WarningLevel>
30 <WarningLevel>4</WarningLevel>
31 <ConsolePause>false</ConsolePause>
31 <ConsolePause>false</ConsolePause>
32 </PropertyGroup>
32 </PropertyGroup>
33 <ItemGroup>
33 <ItemGroup>
34 <Reference Include="System" />
34 <Reference Include="System" />
35 <Reference Include="nunit.framework">
35 <Reference Include="nunit.framework">
36 <HintPath>..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
36 <HintPath>..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
37 </Reference>
37 </Reference>
38 </ItemGroup>
38 </ItemGroup>
39 <ItemGroup>
39 <ItemGroup>
40 <Compile Include="JsonTests.cs" />
40 <Compile Include="JsonTests.cs" />
41 </ItemGroup>
41 </ItemGroup>
42 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
42 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
43 <ItemGroup>
43 <ItemGroup>
44 <ProjectReference Include="..\..\Implab\Implab.csproj">
44 <ProjectReference Include="..\..\Implab\Implab.csproj">
45 <Project>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</Project>
45 <Project>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</Project>
46 <Name>Implab</Name>
46 <Name>Implab</Name>
47 </ProjectReference>
47 </ProjectReference>
48 </ItemGroup>
48 </ItemGroup>
49 <ItemGroup>
49 <ItemGroup>
50 <None Include="packages.config" />
50 <None Include="packages.config" />
51 </ItemGroup>
51 </ItemGroup>
52 <ItemGroup>
53 <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
54 </ItemGroup>
52 </Project> No newline at end of file
55 </Project>
@@ -1,75 +1,81
1 <?xml version="1.0" encoding="utf-8"?>
1 <?xml version="1.0" encoding="utf-8"?>
2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <PropertyGroup>
3 <PropertyGroup>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6 <ProductVersion>8.0.30703</ProductVersion>
6 <ProductVersion>8.0.30703</ProductVersion>
7 <SchemaVersion>2.0</SchemaVersion>
7 <SchemaVersion>2.0</SchemaVersion>
8 <ProjectGuid>{2BD05F84-E067-4B87-9477-FDC2676A21C6}</ProjectGuid>
8 <ProjectGuid>{2BD05F84-E067-4B87-9477-FDC2676A21C6}</ProjectGuid>
9 <OutputType>Library</OutputType>
9 <OutputType>Library</OutputType>
10 <RootNamespace>Implab.Test</RootNamespace>
10 <RootNamespace>Implab.Test</RootNamespace>
11 <AssemblyName>Implab.Test</AssemblyName>
11 <AssemblyName>Implab.Test</AssemblyName>
12 <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
12 <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
13 <ReleaseVersion>0.2</ReleaseVersion>
13 <ReleaseVersion>0.2</ReleaseVersion>
14 </PropertyGroup>
14 </PropertyGroup>
15 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
15 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
16 <DebugSymbols>true</DebugSymbols>
16 <DebugSymbols>true</DebugSymbols>
17 <DebugType>full</DebugType>
17 <DebugType>full</DebugType>
18 <Optimize>false</Optimize>
18 <Optimize>false</Optimize>
19 <OutputPath>bin\Debug</OutputPath>
19 <OutputPath>bin\Debug</OutputPath>
20 <DefineConstants>DEBUG;MONO</DefineConstants>
20 <DefineConstants>DEBUG;MONO</DefineConstants>
21 <ErrorReport>prompt</ErrorReport>
21 <ErrorReport>prompt</ErrorReport>
22 <WarningLevel>4</WarningLevel>
22 <WarningLevel>4</WarningLevel>
23 <ConsolePause>false</ConsolePause>
23 <ConsolePause>false</ConsolePause>
24 </PropertyGroup>
24 </PropertyGroup>
25 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
25 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
26 <Optimize>true</Optimize>
26 <Optimize>true</Optimize>
27 <OutputPath>bin\Release</OutputPath>
27 <OutputPath>bin\Release</OutputPath>
28 <ErrorReport>prompt</ErrorReport>
28 <ErrorReport>prompt</ErrorReport>
29 <WarningLevel>4</WarningLevel>
29 <WarningLevel>4</WarningLevel>
30 <ConsolePause>false</ConsolePause>
30 <ConsolePause>false</ConsolePause>
31 <DefineConstants>MONO</DefineConstants>
31 <DefineConstants>MONO</DefineConstants>
32 </PropertyGroup>
32 </PropertyGroup>
33 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' ">
33 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' ">
34 <DebugSymbols>true</DebugSymbols>
34 <DebugSymbols>true</DebugSymbols>
35 <DebugType>full</DebugType>
35 <DebugType>full</DebugType>
36 <Optimize>false</Optimize>
36 <Optimize>false</Optimize>
37 <OutputPath>bin\Debug</OutputPath>
37 <OutputPath>bin\Debug</OutputPath>
38 <DefineConstants>DEBUG;TRACE;NET_4_5;MONO</DefineConstants>
38 <DefineConstants>DEBUG;TRACE;NET_4_5;MONO</DefineConstants>
39 <ErrorReport>prompt</ErrorReport>
39 <ErrorReport>prompt</ErrorReport>
40 <WarningLevel>4</WarningLevel>
40 <WarningLevel>4</WarningLevel>
41 <ConsolePause>false</ConsolePause>
41 <ConsolePause>false</ConsolePause>
42 </PropertyGroup>
42 </PropertyGroup>
43 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' ">
43 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' ">
44 <Optimize>true</Optimize>
44 <Optimize>true</Optimize>
45 <OutputPath>bin\Release</OutputPath>
45 <OutputPath>bin\Release</OutputPath>
46 <DefineConstants>NET_4_5;MONO</DefineConstants>
46 <DefineConstants>NET_4_5;MONO</DefineConstants>
47 <ErrorReport>prompt</ErrorReport>
47 <ErrorReport>prompt</ErrorReport>
48 <WarningLevel>4</WarningLevel>
48 <WarningLevel>4</WarningLevel>
49 <ConsolePause>false</ConsolePause>
49 <ConsolePause>false</ConsolePause>
50 </PropertyGroup>
50 </PropertyGroup>
51 <ItemGroup>
51 <ItemGroup>
52 <Reference Include="nunit.framework, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
53 <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
54 <Private>True</Private>
55 </Reference>
52 <Reference Include="System" />
56 <Reference Include="System" />
53 <Reference Include="nunit.framework" />
54 </ItemGroup>
57 </ItemGroup>
55 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
58 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
56 <ItemGroup>
59 <ItemGroup>
57 <Compile Include="AsyncTests.cs" />
60 <Compile Include="AsyncTests.cs" />
58 <Compile Include="PromiseHelper.cs" />
61 <Compile Include="PromiseHelper.cs" />
59 <Compile Include="Properties\AssemblyInfo.cs" />
62 <Compile Include="Properties\AssemblyInfo.cs" />
60 <Compile Include="CancelationTests.cs" />
63 <Compile Include="CancelationTests.cs" />
61 <Compile Include="RunnableComponentTests.cs" />
64 <Compile Include="RunnableComponentTests.cs" />
62 <Compile Include="PollingComponentTests.cs" />
65 <Compile Include="PollingComponentTests.cs" />
63 <Compile Include="Mock\MockRunnableComponent.cs" />
66 <Compile Include="Mock\MockRunnableComponent.cs" />
64 <Compile Include="Mock\MockPollingComponent.cs" />
67 <Compile Include="Mock\MockPollingComponent.cs" />
65 </ItemGroup>
68 </ItemGroup>
66 <ItemGroup>
69 <ItemGroup>
67 <ProjectReference Include="..\Implab\Implab.csproj">
70 <ProjectReference Include="..\Implab\Implab.csproj">
68 <Project>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</Project>
71 <Project>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</Project>
69 <Name>Implab</Name>
72 <Name>Implab</Name>
70 </ProjectReference>
73 </ProjectReference>
71 </ItemGroup>
74 </ItemGroup>
72 <ItemGroup>
75 <ItemGroup>
73 <Folder Include="Mock\" />
76 <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
77 </ItemGroup>
78 <ItemGroup>
79 <None Include="packages.config" />
74 </ItemGroup>
80 </ItemGroup>
75 </Project> No newline at end of file
81 </Project>
@@ -1,71 +1,71
1 using System;
1 using System;
2 using Implab.Components;
2 using Implab.Components;
3
3
4 namespace Implab.Test.Mock {
4 namespace Implab.Test.Mock {
5 class MockPollingComponent : PollingComponent {
5 class MockPollingComponent : PollingComponent {
6 public MockPollingComponent(TimeSpan interval, Func<Func<ICancellationToken, IPromise>, IPromise> dispatcher, bool initialized) : base(interval, dispatcher, initialized) {
6 public MockPollingComponent(TimeSpan interval, Func<Func<ICancellationToken, IPromise>, IPromise> dispatcher, bool initialized) : base(interval, dispatcher, initialized) {
7 }
7 }
8
8
9 public Action MockInit {
9 public Action MockInit {
10 get;
10 get;
11 set;
11 set;
12 }
12 }
13
13
14 public Action<Exception> MockOnError {
14 public Action<Exception> MockOnError {
15 get;
15 get;
16 set;
16 set;
17 }
17 }
18
18
19 public Action<Exception> MockOnCancel {
19 public Action<Exception> MockOnCancel {
20 get;
20 get;
21 set;
21 set;
22 }
22 }
23
23
24 public Func<IPromise> MockStart {
24 public Func<IPromise> MockStart {
25 get;
25 get;
26 set;
26 set;
27 }
27 }
28
28
29 public Func<IPromise> MockStop {
29 public Func<IPromise> MockStop {
30 get;
30 get;
31 set;
31 set;
32 }
32 }
33
33
34 public Func<ICancellationToken, IPromise> MockTick {
34 public Func<ICancellationToken, IPromise> MockTick {
35 get;
35 get;
36 set;
36 set;
37 }
37 }
38
38
39 protected override IPromise OnStart() {
39 protected override IPromise OnStart() {
40 return MockStart != null ? Safe.Run(MockStart).Chain(base.OnStart) : Safe.Run(base.OnStart);
40 return MockStart != null ? Safe.Run(MockStart).Chain(base.OnStart) : Safe.Run(base.OnStart);
41 }
41 }
42
42
43 protected override IPromise OnStop() {
43 protected override IPromise OnStop() {
44 return MockStop != null ? Safe.Run(MockStop).Chain(base.OnStop) : Safe.Run(base.OnStop);
44 return MockStop != null ? Safe.Run(MockStop).Chain(base.OnStop) : Safe.Run(base.OnStop);
45 }
45 }
46
46
47 protected override void OnInitialize() {
47 protected override void OnInitialize() {
48 if (MockInit != null)
48 if (MockInit != null)
49 MockInit();
49 MockInit();
50 }
50 }
51
51
52 protected override IPromise OnTick(ICancellationToken cancellationToken) {
52 protected override IPromise OnTick(ICancellationToken cancellationToken) {
53 return MockTick != null ? Safe.Run(() => MockTick(cancellationToken)) : Promise.SUCCESS;
53 return MockTick != null ? Safe.Run(() => MockTick(cancellationToken)) : Promise.Success;
54 }
54 }
55
55
56 protected override void OnTickCancel(Exception error) {
56 protected override void OnTickCancel(Exception error) {
57 if (MockOnCancel != null)
57 if (MockOnCancel != null)
58 MockOnCancel(error);
58 MockOnCancel(error);
59 }
59 }
60
60
61 protected override void OnTickError(Exception error) {
61 protected override void OnTickError(Exception error) {
62 if (MockOnError != null)
62 if (MockOnError != null)
63 MockOnError(error);
63 MockOnError(error);
64 }
64 }
65
65
66 public void CallComponentFail(Exception error) {
66 public void CallComponentFail(Exception error) {
67 Fail(error);
67 Fail(error);
68 }
68 }
69 }
69 }
70 }
70 }
71
71
@@ -1,38 +1,52
1 using System;
1 using System;
2 using Implab.Components;
2 using Implab.Components;
3
3
4 namespace Implab.Test.Mock {
4 namespace Implab.Test.Mock {
5 class MockRunnableComponent : RunnableComponent {
5 class MockRunnableComponent : RunnableComponent {
6 public MockRunnableComponent(bool initialized) : base(initialized) {
6 public MockRunnableComponent(bool initialized) : base(initialized) {
7 }
7 }
8
8
9 public MockRunnableComponent(bool initialized, bool reusable) : base(initialized, reusable) {
10 }
11
9 public Action MockInit {
12 public Action MockInit {
10 get;
13 get;
11 set;
14 set;
12 }
15 }
13
16
14 public Func<IPromise> MockStart {
17 public Func<IPromise> MockStart {
15 get;
18 get;
16 set;
19 set;
17 }
20 }
18
21
19 public Func<IPromise> MockStop {
22 public Func<IPromise> MockStop {
20 get;
23 get;
21 set;
24 set;
22 }
25 }
23
26
27 public Action<bool, Exception> MockDispose {
28 get;
29 set;
30 }
31
24 protected override IPromise OnStart() {
32 protected override IPromise OnStart() {
25 return MockStart != null ? Safe.Run(MockStart).Chain(base.OnStart) : Safe.Run(base.OnStart);
33 return MockStart != null ? Safe.Run(MockStart).Chain(base.OnStart) : Safe.Run(base.OnStart);
26 }
34 }
27
35
28 protected override IPromise OnStop() {
36 protected override IPromise OnStop() {
29 return MockStop != null ? Safe.Run(MockStop).Chain(base.OnStop) : Safe.Run(base.OnStop);
37 return MockStop != null ? Safe.Run(MockStop).Chain(base.OnStop) : Safe.Run(base.OnStop);
30 }
38 }
31
39
32 protected override void OnInitialize() {
40 protected override void OnInitialize() {
33 if (MockInit != null)
41 if (MockInit != null)
34 MockInit();
42 MockInit();
35 }
43 }
44
45 protected override void Dispose(bool disposing, Exception lastError) {
46 if (MockDispose != null)
47 MockDispose(disposing, lastError);
48 base.Dispose(disposing, lastError);
49 }
36 }
50 }
37 }
51 }
38
52
@@ -1,230 +1,230
1 using System;
1 using System;
2 using System.Reflection;
2 using System.Reflection;
3 using System.Threading;
3 using System.Threading;
4 using Implab.Parallels;
4 using Implab.Parallels;
5 using Implab.Components;
5 using Implab.Components;
6 using Implab.Test.Mock;
6 using Implab.Test.Mock;
7
7
8 #if MONO
8 #if MONO
9
9
10 using NUnit.Framework;
10 using NUnit.Framework;
11 using TestClassAttribute = NUnit.Framework.TestFixtureAttribute;
11 using TestClassAttribute = NUnit.Framework.TestFixtureAttribute;
12 using TestMethodAttribute = NUnit.Framework.TestAttribute;
12 using TestMethodAttribute = NUnit.Framework.TestAttribute;
13 using AssertFailedException = NUnit.Framework.AssertionException;
13 using AssertFailedException = NUnit.Framework.AssertionException;
14 #else
14 #else
15
15
16 using Microsoft.VisualStudio.TestTools.UnitTesting;
16 using Microsoft.VisualStudio.TestTools.UnitTesting;
17
17
18 #endif
18 #endif
19
19
20 namespace Implab.Test {
20 namespace Implab.Test {
21 [TestClass]
21 [TestClass]
22 public class PollingComponentTests {
22 public class PollingComponentTests {
23 static void ShouldThrow(Action action) {
23 static void ShouldThrow(Action action) {
24 try {
24 try {
25 action();
25 action();
26 Assert.Fail();
26 Assert.Fail();
27 } catch (AssertFailedException) {
27 } catch (AssertFailedException) {
28 throw;
28 throw;
29 } catch {
29 } catch {
30 }
30 }
31 }
31 }
32
32
33 [TestMethod]
33 [TestMethod]
34 public void NormalFlowTest() {
34 public void NormalFlowTest() {
35 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, false);
35 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, false);
36
36
37 Assert.AreEqual(ExecutionState.Created, comp.State);
37 Assert.AreEqual(ExecutionState.Created, comp.State);
38
38
39 comp.Init();
39 comp.Initialize();
40
40
41 Assert.AreEqual(ExecutionState.Ready, comp.State);
41 Assert.AreEqual(ExecutionState.Ready, comp.State);
42
42
43 comp.Start().Join(1000);
43 comp.Start().Join(1000);
44
44
45 Assert.AreEqual(ExecutionState.Running, comp.State);
45 Assert.AreEqual(ExecutionState.Running, comp.State);
46
46
47 comp.Stop().Join(1000);
47 comp.Stop().Join(1000);
48
48
49 Assert.AreEqual(ExecutionState.Disposed, comp.State);
49 Assert.AreEqual(ExecutionState.Disposed, comp.State);
50
50
51 }
51 }
52
52
53 [TestMethod]
53 [TestMethod]
54 public void ShouldStartTicks() {
54 public void ShouldStartTicks() {
55 var signal = new Signal();
55 var signal = new Signal();
56
56
57 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
57 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
58 comp.MockTick = ct => {
58 comp.MockTick = ct => {
59 signal.Set();
59 signal.Set();
60 return Promise.SUCCESS;
60 return Promise.Success;
61 };
61 };
62
62
63 comp.Start().Join(1000);
63 comp.Start().Join(1000);
64 signal.Wait(1000);
64 signal.Wait(1000);
65 comp.Stop().Join(1000);
65 comp.Stop().Join(1000);
66 }
66 }
67
67
68 [TestMethod]
68 [TestMethod]
69 public void StopShouldWaitForTickToComplete() {
69 public void StopShouldWaitForTickToComplete() {
70 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
70 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
71 var signal = new Signal();
71 var signal = new Signal();
72 var promise = new Promise();
72 var promise = new Promise();
73
73
74 // timer should tick once
74 // timer should tick once
75 comp.MockTick = ct => {
75 comp.MockTick = ct => {
76 signal.Set();
76 signal.Set();
77 return promise;
77 return promise;
78 };
78 };
79
79
80 // start timer
80 // start timer
81 comp.Start().Join(1000);
81 comp.Start().Join(1000);
82
82
83 signal.Wait(); // wait for tick
83 signal.Wait(); // wait for tick
84
84
85 // try to stop component
85 // try to stop component
86 var stopping = comp.Stop();
86 var stopping = comp.Stop();
87
87
88 Assert.AreEqual(ExecutionState.Stopping, comp.State);
88 Assert.AreEqual(ExecutionState.Stopping, comp.State);
89 ShouldThrow(() => stopping.Join(100));
89 ShouldThrow(() => stopping.Join(100));
90 Assert.AreEqual(ExecutionState.Stopping, comp.State);
90 Assert.AreEqual(ExecutionState.Stopping, comp.State);
91
91
92 // complete operation
92 // complete operation
93 promise.Resolve();
93 promise.Resolve();
94
94
95 // the component should stop normally
95 // the component should stop normally
96 stopping.Join(1000);
96 stopping.Join(1000);
97
97
98 Assert.AreEqual(ExecutionState.Disposed, comp.State);
98 Assert.AreEqual(ExecutionState.Disposed, comp.State);
99 }
99 }
100
100
101 [TestMethod]
101 [TestMethod]
102 public void ShouldRecoverAfterTickError() {
102 public void ShouldRecoverAfterTickError() {
103 var ticks = 0;
103 var ticks = 0;
104
104
105 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
105 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
106 var signal = new Signal(); // will signal when timer fires 10 times
106 var signal = new Signal(); // will signal when timer fires 10 times
107
107
108 comp.MockTick = ct => {
108 comp.MockTick = ct => {
109 ticks++;
109 ticks++;
110 if (ticks == 10)
110 if (ticks == 10)
111 signal.Set();
111 signal.Set();
112 // each time handler dies
112 // each time handler dies
113 throw new Exception("tainted handler");
113 throw new Exception("tainted handler");
114 };
114 };
115
115
116 comp.Start();
116 comp.Start();
117
117
118 signal.Wait(1000);
118 signal.Wait(1000);
119
119
120 comp.Stop().Join(1000);
120 comp.Stop().Join(1000);
121
121
122 Assert.AreEqual(ExecutionState.Disposed, comp.State);
122 Assert.AreEqual(ExecutionState.Disposed, comp.State);
123 }
123 }
124
124
125 [TestMethod]
125 [TestMethod]
126 public void StopCancelHandlerOnStop() {
126 public void StopCancelHandlerOnStop() {
127 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
127 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
128 var started = new Signal();
128 var started = new Signal();
129 bool cancelled = false;
129 bool cancelled = false;
130
130
131 // timer should tick once
131 // timer should tick once
132 comp.MockTick = ct => {
132 comp.MockTick = ct => {
133 started.Set();
133 started.Set();
134
134
135 while(!ct.IsCancellationRequested) {
135 while(!ct.IsCancellationRequested) {
136 Thread.Sleep(1);
136 Thread.Sleep(1);
137 }
137 }
138
138
139 cancelled = true;
139 cancelled = true;
140
140
141 throw new OperationCanceledException();
141 throw new OperationCanceledException();
142 };
142 };
143
143
144 // start timer
144 // start timer
145 comp.Start().Join(1000);
145 comp.Start().Join(1000);
146
146
147 started.Wait(); // wait for tick
147 started.Wait(); // wait for tick
148
148
149 // try to stop component
149 // try to stop component
150 comp.Stop().Join(1000);
150 comp.Stop().Join(1000);
151
151
152 Assert.AreEqual(true, cancelled);
152 Assert.AreEqual(true, cancelled);
153
153
154 Assert.AreEqual(ExecutionState.Disposed, comp.State);
154 Assert.AreEqual(ExecutionState.Disposed, comp.State);
155 }
155 }
156
156
157 [TestMethod]
157 [TestMethod]
158 public void FailTickOnStopShouldBeIgnored() {
158 public void FailTickOnStopShouldBeIgnored() {
159 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
159 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
160 var started = new Signal();
160 var started = new Signal();
161 var finish = new Signal();
161 var finish = new Signal();
162
162
163 // timer should tick once
163 // timer should tick once
164 comp.MockTick = ct => {
164 comp.MockTick = ct => {
165 started.Set();
165 started.Set();
166 finish.Wait();
166 finish.Wait();
167 // component is in stopping state here
167 // component is in stopping state here
168 throw new Exception("Die, die, die!!!");
168 throw new Exception("Die, die, die!!!");
169 };
169 };
170
170
171
171
172 comp.MockOnError = comp.CallComponentFail;
172 comp.MockOnError = comp.CallComponentFail;
173
173
174 // start timer
174 // start timer
175 comp.Start().Join(1000);
175 comp.Start().Join(1000);
176
176
177 started.Wait(); // wait for tick
177 started.Wait(); // wait for tick
178
178
179 // try to stop component
179 // try to stop component
180 var stopping = comp.Stop();
180 var stopping = comp.Stop();
181
181
182 // the component is in stopping state but it is waiting for the tick handler to complete
182 // the component is in stopping state but it is waiting for the tick handler to complete
183 finish.Set(); // signal the tick handler to finish
183 finish.Set(); // signal the tick handler to finish
184
184
185 // tick handler should stop rather soon
185 // tick handler should stop rather soon
186 stopping.Join(1000);
186 stopping.Join(1000);
187
187
188 // validate the component is disposed
188 // validate the component is disposed
189 Assert.AreEqual(ExecutionState.Disposed, comp.State);
189 Assert.AreEqual(ExecutionState.Disposed, comp.State);
190 }
190 }
191
191
192 [TestMethod]
192 [TestMethod]
193 public void FailTickShouldFailComponent() {
193 public void FailTickShouldFailComponent() {
194 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
194 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
195 var started = new Signal();
195 var started = new Signal();
196 var finish = new Signal();
196 var finish = new Signal();
197
197
198 // timer should tick once
198 // timer should tick once
199 comp.MockTick = ct => {
199 comp.MockTick = ct => {
200 started.Set();
200 started.Set();
201 throw new Exception("Die, die, die!!!");
201 throw new Exception("Die, die, die!!!");
202 };
202 };
203
203
204
204
205 comp.MockOnError = err => {
205 comp.MockOnError = err => {
206 comp.CallComponentFail(err);
206 comp.CallComponentFail(err);
207 finish.Set();
207 finish.Set();
208 };
208 };
209
209
210 // start timer
210 // start timer
211 comp.Start().Join(1000);
211 comp.Start().Join(1000);
212
212
213 started.Wait(); // wait for tick
213 started.Wait(); // wait for tick
214
214
215 finish.Wait();
215 finish.Wait();
216
216
217 // try to stop component
217 // try to stop component
218 ShouldThrow(() => comp.Stop());
218 ShouldThrow(() => comp.Stop());
219
219
220 Assert.AreEqual(ExecutionState.Failed, comp.State);
220 Assert.AreEqual(ExecutionState.Failed, comp.State);
221 Assert.IsNotNull(comp.LastError);
221 Assert.IsNotNull(comp.LastError);
222 Assert.AreEqual("Die, die, die!!!", comp.LastError.Message);
222 Assert.AreEqual("Die, die, die!!!", comp.LastError.Message);
223
223
224 comp.Dispose();
224 comp.Dispose();
225 Assert.AreEqual(ExecutionState.Disposed, comp.State);
225 Assert.AreEqual(ExecutionState.Disposed, comp.State);
226 }
226 }
227
227
228 }
228 }
229 }
229 }
230
230
@@ -1,165 +1,230
1 using System;
1 using System;
2 using System.Reflection;
2 using System.Reflection;
3 using System.Threading;
3 using System.Threading;
4 using Implab.Parallels;
4 using Implab.Parallels;
5 using Implab.Components;
5 using Implab.Components;
6 using Implab.Test.Mock;
6 using Implab.Test.Mock;
7
7
8 #if MONO
8 #if MONO
9
9
10 using NUnit.Framework;
10 using NUnit.Framework;
11 using TestClassAttribute = NUnit.Framework.TestFixtureAttribute;
11 using TestClassAttribute = NUnit.Framework.TestFixtureAttribute;
12 using TestMethodAttribute = NUnit.Framework.TestAttribute;
12 using TestMethodAttribute = NUnit.Framework.TestAttribute;
13 using AssertFailedException = NUnit.Framework.AssertionException;
13 using AssertFailedException = NUnit.Framework.AssertionException;
14 #else
14 #else
15
15
16 using Microsoft.VisualStudio.TestTools.UnitTesting;
16 using Microsoft.VisualStudio.TestTools.UnitTesting;
17
17
18 #endif
18 #endif
19
19
20 namespace Implab.Test {
20 namespace Implab.Test {
21 [TestClass]
21 [TestClass]
22 public class RunnableComponentTests {
22 public class RunnableComponentTests {
23
23
24 static void ShouldThrow(Action action) {
24 static void ShouldThrow(Action action) {
25 try {
25 try {
26 action();
26 action();
27 Assert.Fail();
27 Assert.Fail();
28 } catch (AssertFailedException) {
28 } catch (AssertFailedException) {
29 throw;
29 throw;
30 } catch {
30 } catch {
31 }
31 }
32 }
32 }
33
33
34
34
35
35
36 [TestMethod]
36 [TestMethod]
37 public void NormalFlowTest() {
37 public void NormalFlowTest() {
38 var comp = new MockRunnableComponent(false);
38 var comp = new MockRunnableComponent(false);
39
39
40 Assert.AreEqual(ExecutionState.Created, comp.State);
40 Assert.AreEqual(ExecutionState.Created, comp.State);
41
41
42 comp.Init();
42 comp.Initialize();
43
43
44 Assert.AreEqual(ExecutionState.Ready, comp.State);
44 Assert.AreEqual(ExecutionState.Ready, comp.State);
45
45
46 comp.Start().Join(1000);
46 comp.Start().Join(1000);
47
47
48 Assert.AreEqual(ExecutionState.Running, comp.State);
48 Assert.AreEqual(ExecutionState.Running, comp.State);
49
49
50 comp.Stop().Join(1000);
50 comp.Stop().Join(1000);
51
51
52 Assert.AreEqual(ExecutionState.Disposed, comp.State);
52 Assert.AreEqual(ExecutionState.Disposed, comp.State);
53
53
54 }
54 }
55
55
56 [TestMethod]
56 [TestMethod]
57 public void InitFailTest() {
57 public void InitFailTest() {
58 var comp = new MockRunnableComponent(false) {
58 var comp = new MockRunnableComponent(false) {
59 MockInit = () => {
59 MockInit = () => {
60 throw new Exception("BAD");
60 throw new Exception("BAD");
61 }
61 }
62 };
62 };
63
63
64 ShouldThrow(() => comp.Start());
64 ShouldThrow(() => comp.Start());
65 ShouldThrow(() => comp.Stop());
65 ShouldThrow(() => comp.Stop());
66 Assert.AreEqual(ExecutionState.Created, comp.State);
66 Assert.AreEqual(ExecutionState.Created, comp.State);
67
67
68 ShouldThrow(comp.Init);
68 ShouldThrow(comp.Initialize);
69
69
70 Assert.AreEqual(ExecutionState.Failed, comp.State);
70 Assert.AreEqual(ExecutionState.Failed, comp.State);
71
71
72 ShouldThrow(() => comp.Start());
72 ShouldThrow(() => comp.Start());
73 ShouldThrow(() => comp.Stop());
73 ShouldThrow(() => comp.Stop());
74 Assert.AreEqual(ExecutionState.Failed, comp.State);
74 Assert.AreEqual(ExecutionState.Failed, comp.State);
75
75
76 comp.Dispose();
76 comp.Dispose();
77 Assert.AreEqual(ExecutionState.Disposed, comp.State);
77 Assert.AreEqual(ExecutionState.Disposed, comp.State);
78 }
78 }
79
79
80 [TestMethod]
80 [TestMethod]
81 public void DisposedTest() {
81 public void DisposedTest() {
82
82
83 var comp = new MockRunnableComponent(false);
83 var comp = new MockRunnableComponent(false);
84 comp.Dispose();
84 comp.Dispose();
85
85
86 ShouldThrow(() => comp.Start());
86 ShouldThrow(() => comp.Start());
87 ShouldThrow(() => comp.Stop());
87 ShouldThrow(() => comp.Stop());
88 ShouldThrow(comp.Init);
88 ShouldThrow(comp.Initialize);
89
90 Assert.AreEqual(ExecutionState.Disposed, comp.State);
91 }
92
93 [TestMethod]
94 public void ShouldCallDisposeOnStop() {
95 var comp = new MockRunnableComponent(true);
96
97 bool disposed = false;
98 comp.MockDispose = (disposing, error) => {
99 disposed = true;
100 };
101
102 comp.Start().Join(1000);
103 comp.Stop().Join(1000);
104
105 ShouldThrow(() => comp.Start());
106 ShouldThrow(() => comp.Stop());
107 ShouldThrow(comp.Initialize);
89
108
90 Assert.AreEqual(ExecutionState.Disposed, comp.State);
109 Assert.AreEqual(ExecutionState.Disposed, comp.State);
110 Assert.IsTrue(disposed);
111 }
112
113 [TestMethod]
114 public void ShouldNotCallDisposeOnStop() {
115 var comp = new MockRunnableComponent(true, true);
116
117 bool disposed = false;
118 comp.MockDispose = (disposing, error) => {
119 disposed = true;
120 };
121
122 comp.Start().Join(1000);
123 comp.Stop().Join(1000);
124
125 Assert.AreEqual(ExecutionState.Ready, comp.State);
126 Assert.IsFalse(disposed);
127 }
128
129 [TestMethod]
130 public void SelfDisposeOnStop() {
131 var comp = new MockRunnableComponent(true, true);
132
133 bool disposed = false;
134 Exception lastError = null;
135 comp.MockDispose = (disposing, error) => {
136 disposed = true;
137 lastError = error;
138 };
139
140 comp.Start().Join(1000);
141 comp.Stop().Join(1000);
142
143 Assert.AreEqual(ExecutionState.Ready, comp.State);
144 Assert.IsFalse(disposed);
145
146 comp.MockStop = () => {
147 comp.Dispose();
148 return Promise.Success;
149 };
150
151 comp.Start().Join(1000);
152 comp.Stop().Join(1000);
153
154 Assert.AreEqual(ExecutionState.Disposed, comp.State);
155 Assert.IsTrue(disposed);
91 }
156 }
92
157
93 [TestMethod]
158 [TestMethod]
94 public void StartCancelTest() {
159 public void StartCancelTest() {
95 var comp = new MockRunnableComponent(true) {
160 var comp = new MockRunnableComponent(true) {
96 MockStart = () => PromiseHelper.Sleep(100000, 0)
161 MockStart = () => PromiseHelper.Sleep(100000, 0)
97 };
162 };
98
163
99 var p = comp.Start();
164 var p = comp.Start();
100 Assert.AreEqual(ExecutionState.Starting, comp.State);
165 Assert.AreEqual(ExecutionState.Starting, comp.State);
101 p.Cancel();
166 p.Cancel();
102 ShouldThrow(() => p.Join(1000));
167 ShouldThrow(() => p.Join(1000));
103 Assert.AreEqual(ExecutionState.Failed, comp.State);
168 Assert.AreEqual(ExecutionState.Failed, comp.State);
104
169
105 Assert.IsTrue(comp.LastError is OperationCanceledException);
170 Assert.IsTrue(comp.LastError is OperationCanceledException);
106
171
107 comp.Dispose();
172 comp.Dispose();
108 }
173 }
109
174
110 [TestMethod]
175 [TestMethod]
111 public void StartStopTest() {
176 public void StartStopTest() {
112 var stop = new Signal();
177 var stop = new Signal();
113 var comp = new MockRunnableComponent(true) {
178 var comp = new MockRunnableComponent(true) {
114 MockStart = () => PromiseHelper.Sleep(100000, 0),
179 MockStart = () => PromiseHelper.Sleep(100000, 0),
115 MockStop = () => AsyncPool.RunThread(stop.Wait)
180 MockStop = () => AsyncPool.RunThread(stop.Wait)
116 };
181 };
117
182
118 var p1 = comp.Start();
183 var p1 = comp.Start();
119 var p2 = comp.Stop();
184 var p2 = comp.Stop();
120 // should enter stopping state
185 // should enter stopping state
121
186
122 ShouldThrow(p1.Join);
187 ShouldThrow(p1.Join);
123 Assert.IsTrue(p1.IsCancelled);
188 Assert.IsTrue(p1.IsCancelled);
124 Assert.AreEqual(ExecutionState.Stopping, comp.State);
189 Assert.AreEqual(ExecutionState.Stopping, comp.State);
125
190
126 stop.Set();
191 stop.Set();
127 p2.Join(1000);
192 p2.Join(1000);
128 Assert.AreEqual(ExecutionState.Disposed, comp.State);
193 Assert.AreEqual(ExecutionState.Disposed, comp.State);
129 }
194 }
130
195
131 [TestMethod]
196 [TestMethod]
132 public void StartStopFailTest() {
197 public void StartStopFailTest() {
133 var comp = new MockRunnableComponent(true) {
198 var comp = new MockRunnableComponent(true) {
134 MockStart = () => PromiseHelper.Sleep(100000, 0).Then(null,null,x => { throw new Exception("I'm dead"); })
199 MockStart = () => PromiseHelper.Sleep(100000, 0).Then(null,null,x => { throw new Exception("I'm dead"); })
135 };
200 };
136
201
137 comp.Start();
202 comp.Start();
138 var p = comp.Stop();
203 var p = comp.Stop();
139 // if Start fails to cancel, should fail to stop
204 // if Start fails to cancel, should fail to stop
140 ShouldThrow(() => p.Join(1000));
205 ShouldThrow(() => p.Join(1000));
141 Assert.AreEqual(ExecutionState.Failed, comp.State);
206 Assert.AreEqual(ExecutionState.Failed, comp.State);
142 Assert.IsNotNull(comp.LastError);
207 Assert.IsNotNull(comp.LastError);
143 Assert.AreEqual("I'm dead", comp.LastError.Message);
208 Assert.AreEqual("I'm dead", comp.LastError.Message);
144 }
209 }
145
210
146 [TestMethod]
211 [TestMethod]
147 public void StopCancelTest() {
212 public void StopCancelTest() {
148 var comp = new MockRunnableComponent(true) {
213 var comp = new MockRunnableComponent(true) {
149 MockStop = () => PromiseHelper.Sleep(100000, 0)
214 MockStop = () => PromiseHelper.Sleep(100000, 0)
150 };
215 };
151
216
152 comp.Start();
217 comp.Start();
153 var p = comp.Stop();
218 var p = comp.Stop();
154 Assert.AreEqual(ExecutionState.Stopping, comp.State);
219 Assert.AreEqual(ExecutionState.Stopping, comp.State);
155 p.Cancel();
220 p.Cancel();
156 ShouldThrow(() => p.Join(1000));
221 ShouldThrow(() => p.Join(1000));
157 Assert.AreEqual(ExecutionState.Failed, comp.State);
222 Assert.AreEqual(ExecutionState.Failed, comp.State);
158 Assert.IsTrue(comp.LastError is OperationCanceledException);
223 Assert.IsTrue(comp.LastError is OperationCanceledException);
159
224
160 comp.Dispose();
225 comp.Dispose();
161 }
226 }
162
227
163 }
228 }
164 }
229 }
165
230
@@ -1,33 +1,41
1 using System;
1 using System;
2
2
3 namespace Implab.Automaton {
3 namespace Implab.Automaton {
4 public struct AutomatonTransition : IEquatable<AutomatonTransition> {
4 public struct AutomatonTransition : IEquatable<AutomatonTransition> {
5 public readonly int s1;
5 public readonly int s1;
6 public readonly int s2;
6 public readonly int s2;
7 public readonly int edge;
7 public readonly int edge;
8
8
9 public AutomatonTransition(int s1, int s2, int edge) {
9 public AutomatonTransition(int s1, int s2, int edge) {
10 this.s1 = s1;
10 this.s1 = s1;
11 this.s2 = s2;
11 this.s2 = s2;
12 this.edge = edge;
12 this.edge = edge;
13 }
13 }
14
14
15
15
16 #region IEquatable implementation
16 #region IEquatable implementation
17 public bool Equals(AutomatonTransition other) {
17 public bool Equals(AutomatonTransition other) {
18 return other.s1 == s1 && other.s2 == s2 && other.edge == edge ;
18 return other.s1 == s1 && other.s2 == s2 && other.edge == edge ;
19 }
19 }
20 #endregion
20 #endregion
21
21
22 public override bool Equals(object obj) {
22 public override bool Equals(object obj) {
23 if (obj is AutomatonTransition)
23 if (obj is AutomatonTransition)
24 return Equals((AutomatonTransition)obj);
24 return Equals((AutomatonTransition)obj);
25 return base.Equals(obj);
25 return base.Equals(obj);
26 }
26 }
27
27
28 public override int GetHashCode() {
28 public override int GetHashCode() {
29 return s1 + s2 + edge;
29 return s1 + s2 + edge;
30 }
30 }
31
32 public static bool operator == (AutomatonTransition rv, AutomatonTransition lv) {
33 return rv.Equals(lv);
34 }
35
36 public static bool operator !=(AutomatonTransition rv, AutomatonTransition lv) {
37 return rv.Equals(lv);
38 }
31 }
39 }
32 }
40 }
33
41
@@ -1,21 +1,21
1 using System;
1 using System;
2
2
3 namespace Implab.Components {
3 namespace Implab.Components {
4 /// <summary>
4 /// <summary>
5 /// Initializable components are created and initialized in two steps, first we have create the component,
5 /// Initializable components are created and initialized in two steps, first we have create the component,
6 /// then we have to complete it's creation by calling an <see cref="Init()"/> method. All parameters needed
6 /// then we have to complete it's creation by calling an <see cref="Initialize()"/> method. All parameters needed
7 /// to complete the initialization must be passed before the calling <see cref="Init()"/>
7 /// to complete the initialization must be passed before the calling <see cref="Initialize()"/>
8 /// </summary>
8 /// </summary>
9 public interface IInitializable {
9 public interface IInitializable {
10 /// <summary>
10 /// <summary>
11 /// Completes initialization.
11 /// Completes initialization.
12 /// </summary>
12 /// </summary>
13 /// <remarks>
13 /// <remarks>
14 /// Normally virtual methods shouldn't be called from the constructor, due to the incomplete object state, but
14 /// Normally virtual methods shouldn't be called from the constructor, due to the incomplete object state, but
15 /// they can be called from this method. This method is also usefull when we constructing a complex grpah
15 /// they can be called from this method. This method is aьуерщlso usefull when we constructing a complex grpah
16 /// of components where cyclic references may take place.
16 /// of components where cyclic references may take place.
17 /// </remarks>
17 /// </remarks>
18 void Init();
18 void Initialize();
19 }
19 }
20 }
20 }
21
21
@@ -1,20 +1,22
1 using System;
1 using System;
2
2
3 namespace Implab.Components {
3 namespace Implab.Components {
4 public interface IRunnable {
4 public interface IRunnable {
5 /// <summary>
5 /// <summary>
6 /// Starts this instance.
6 /// Starts this instance.
7 /// </summary>
7 /// </summary>
8 IPromise Start();
8 IPromise Start();
9
9
10 /// <summary>
10 /// <summary>
11 /// Stops this instance. After the instance is stopped it can't be started again, stopping should be treated as gracefull and async dispose.
11 /// Stops this instance. After the instance is stopped it can't be started again, stopping should be treated as gracefull and async dispose.
12 /// </summary>
12 /// </summary>
13 IPromise Stop();
13 IPromise Stop();
14
14
15 ExecutionState State { get; }
15 ExecutionState State { get; }
16
16
17 event EventHandler<StateChangeEventArgs> StateChanged;
18
17 Exception LastError { get; }
19 Exception LastError { get; }
18 }
20 }
19 }
21 }
20
22
@@ -1,155 +1,155
1 using System;
1 using System;
2 using System.Threading;
2 using System.Threading;
3 using Implab.Diagnostics;
3 using Implab.Diagnostics;
4
4
5 namespace Implab.Components {
5 namespace Implab.Components {
6 public class PollingComponent : RunnableComponent {
6 public class PollingComponent : RunnableComponent {
7 readonly Timer m_timer;
7 readonly Timer m_timer;
8 readonly Func<Func<ICancellationToken, IPromise>, IPromise> m_dispatcher;
8 readonly Func<Func<ICancellationToken, IPromise>, IPromise> m_dispatcher;
9 readonly TimeSpan m_interval;
9 readonly TimeSpan m_interval;
10
10
11 readonly object m_lock = new object();
11 readonly object m_lock = new object();
12
12
13 ActionTask m_pending;
13 ActionTask m_pending;
14
14
15 protected PollingComponent(TimeSpan interval, Func<Func<ICancellationToken, IPromise>, IPromise> dispatcher, bool initialized) : base(initialized) {
15 protected PollingComponent(TimeSpan interval, Func<Func<ICancellationToken, IPromise>, IPromise> dispatcher, bool initialized) : base(initialized) {
16 m_timer = new Timer(OnInternalTick);
16 m_timer = new Timer(OnInternalTick);
17
17
18 m_interval = interval;
18 m_interval = interval;
19 m_dispatcher = dispatcher;
19 m_dispatcher = dispatcher;
20 }
20 }
21
21
22 protected override IPromise OnStart() {
22 protected override IPromise OnStart() {
23 m_timer.Change(TimeSpan.Zero, m_interval);
23 m_timer.Change(TimeSpan.Zero, m_interval);
24
24
25 return base.OnStart();
25 return base.OnStart();
26 }
26 }
27
27
28 void OnInternalTick(object state) {
28 void OnInternalTick(object state) {
29 if (StartTick()) {
29 if (StartTick()) {
30 try {
30 try {
31 if (m_dispatcher != null) {
31 if (m_dispatcher != null) {
32 var result = m_dispatcher(OnTick);
32 var result = m_dispatcher(OnTick);
33 m_pending.CancellationRequested(result.Cancel);
33 m_pending.CancellationRequested(result.Cancel);
34 AwaitTick(result);
34 AwaitTick(result);
35 } else {
35 } else {
36 AwaitTick(OnTick(m_pending));
36 AwaitTick(OnTick(m_pending));
37 }
37 }
38 } catch (Exception error) {
38 } catch (Exception error) {
39 HandleTickError(error);
39 HandleTickError(error);
40 }
40 }
41 }
41 }
42 }
42 }
43
43
44 /// <summary>
44 /// <summary>
45 /// Checks wheather there is no running handler in the component and marks that the handler is starting.
45 /// Checks wheather there is no running handler in the component and marks that the handler is starting.
46 /// </summary>
46 /// </summary>
47 /// <returns>boolean value, true - the new tick handler may be invoked, false - a tick handler is already running or a component isn't running.</returns>
47 /// <returns>boolean value, true - the new tick handler may be invoked, false - a tick handler is already running or a component isn't running.</returns>
48 /// <remarks>
48 /// <remarks>
49 /// If the component is stopping no new handlers can be run. Every successful call to this method must be completed with either AwaitTick or HandleTickError handlers.
49 /// If the component is stopping no new handlers can be run. Every successful call to this method must be completed with either AwaitTick or HandleTickError handlers.
50 /// </remarks>
50 /// </remarks>
51 protected virtual bool StartTick() {
51 protected virtual bool StartTick() {
52 lock (m_lock) {
52 lock (m_lock) {
53 if (State != ExecutionState.Running || m_pending != null)
53 if (State != ExecutionState.Running || m_pending != null)
54 return false;
54 return false;
55 // actually the component may be in a not running state here (stopping, disposed or what ever),
55 // actually the component may be in a not running state here (stopping, disposed or what ever),
56 // but OnStop method also locks on the same object and will handle operation in m_pending
56 // but OnStop method also locks on the same object and will handle operation in m_pending
57 m_pending = new ActionTask(
57 m_pending = new ActionTask(
58 () => {
58 () => {
59 // only one operation is running, it's safe to assing m_pending from it
59 // only one operation is running, it's safe to assing m_pending from it
60 m_pending = null;
60 m_pending = null;
61 },
61 },
62 ex => {
62 ex => {
63 try {
63 try {
64 OnTickError(ex);
64 OnTickError(ex);
65 // Analysis disable once EmptyGeneralCatchClause
65 // Analysis disable once EmptyGeneralCatchClause
66 } catch {
66 } catch {
67 } finally {
67 } finally {
68 m_pending = null;
68 m_pending = null;
69 }
69 }
70 // suppress error
70 // suppress error
71 },
71 },
72 ex => {
72 ex => {
73 try {
73 try {
74 OnTickCancel(ex);
74 OnTickCancel(ex);
75 // Analysis disable once EmptyGeneralCatchClause
75 // Analysis disable once EmptyGeneralCatchClause
76 } catch {
76 } catch {
77 } finally {
77 } finally {
78 m_pending = null;
78 m_pending = null;
79 }
79 }
80 // supress cancellation
80 // supress cancellation
81 },
81 },
82 false
82 false
83 );
83 );
84 return true;
84 return true;
85 }
85 }
86 }
86 }
87
87
88 /// <summary>
88 /// <summary>
89 /// Awaits the tick.
89 /// Awaits the tick.
90 /// </summary>
90 /// </summary>
91 /// <param name="tick">Tick.</param>
91 /// <param name="tick">Tick.</param>
92 /// <remarks>
92 /// <remarks>
93 /// This method is called only after StartTick method and m_pending will hold the promise which should be fulfilled.
93 /// This method is called only after StartTick method and m_pending will hold the promise which should be fulfilled.
94 /// </remarks>
94 /// </remarks>
95 void AwaitTick(IPromise tick) {
95 void AwaitTick(IPromise tick) {
96 if (tick == null) {
96 if (tick == null) {
97 m_pending.Resolve();
97 m_pending.Resolve();
98 } else {
98 } else {
99 tick.On(
99 tick.On(
100 m_pending.Resolve,
100 m_pending.Resolve,
101 m_pending.Reject,
101 m_pending.Reject,
102 m_pending.CancelOperation
102 m_pending.CancelOperation
103 );
103 );
104 }
104 }
105 }
105 }
106
106
107 /// <summary>
107 /// <summary>
108 /// Handles the tick error.
108 /// Handles the tick error.
109 /// </summary>
109 /// </summary>
110 /// <remarks>
110 /// <remarks>
111 /// This method is called only after StartTick method and m_pending will hold the promise which should be fulfilled.
111 /// This method is called only after StartTick method and m_pending will hold the promise which should be fulfilled.
112 /// </remarks>
112 /// </remarks>
113 void HandleTickError(Exception error) {
113 void HandleTickError(Exception error) {
114 m_pending.Reject(error);
114 m_pending.Reject(error);
115 }
115 }
116
116
117 protected virtual void OnTickError(Exception error) {
117 protected virtual void OnTickError(Exception error) {
118 }
118 }
119
119
120 protected virtual void OnTickCancel(Exception error) {
120 protected virtual void OnTickCancel(Exception error) {
121 }
121 }
122
122
123 /// <summary>
123 /// <summary>
124 /// Invoked when the timer ticks, use this method to implement your logic
124 /// Invoked when the timer ticks, use this method to implement your logic
125 /// </summary>
125 /// </summary>
126 protected virtual IPromise OnTick(ICancellationToken cancellationToken) {
126 protected virtual IPromise OnTick(ICancellationToken cancellationToken) {
127 return Promise.SUCCESS;
127 return Promise.Success;
128 }
128 }
129
129
130 protected override IPromise OnStop() {
130 protected override IPromise OnStop() {
131 m_timer.Change(-1, -1);
131 m_timer.Change(-1, -1);
132
132
133 // the component is in the stopping state
133 // the component is in the stopping state
134 lock (m_lock) {
134 lock (m_lock) {
135 // after this lock no more pending operations could be created
135 // after this lock no more pending operations could be created
136 var pending = m_pending;
136 var pending = m_pending;
137 // m_pending could be fulfilled and set to null already
137 // m_pending could be fulfilled and set to null already
138 if (pending != null) {
138 if (pending != null) {
139 pending.Cancel();
139 pending.Cancel();
140 return pending.Then(base.OnStop);
140 return pending.Then(base.OnStop);
141 }
141 }
142 }
142 }
143
143
144 return base.OnStop();
144 return base.OnStop();
145 }
145 }
146
146
147 protected override void Dispose(bool disposing, Exception lastError) {
147 protected override void Dispose(bool disposing, Exception lastError) {
148 if (disposing)
148 if (disposing)
149 Safe.Dispose(m_timer);
149 Safe.Dispose(m_timer);
150
150
151 base.Dispose(disposing, lastError);
151 base.Dispose(disposing, lastError);
152 }
152 }
153 }
153 }
154 }
154 }
155
155
@@ -1,296 +1,375
1 using System;
1 using System;
2
2
3 namespace Implab.Components {
3 namespace Implab.Components {
4 public abstract class RunnableComponent : IDisposable, IRunnable, IInitializable {
4 public abstract class RunnableComponent : IDisposable, IRunnable, IInitializable {
5 enum Commands {
5 enum Commands {
6 Ok = 0,
6 Ok = 0,
7 Fail,
7 Fail,
8 Init,
8 Init,
9 Start,
9 Start,
10 Stop,
10 Stop,
11 Dispose,
11 Dispose,
12 Last = Dispose
12 Reset,
13 Last = Reset
13 }
14 }
14
15
15 class StateMachine {
16 class StateMachine {
16 static readonly ExecutionState[,] _transitions;
17 static readonly ExecutionState[,] _transitions;
17
18
18 static StateMachine() {
19 static StateMachine() {
19 _transitions = new ExecutionState[(int)ExecutionState.Last + 1, (int)Commands.Last + 1];
20 _transitions = new ExecutionState[(int)ExecutionState.Last + 1, (int)Commands.Last + 1];
20
21
21 Edge(ExecutionState.Created, ExecutionState.Initializing, Commands.Init);
22 Edge(ExecutionState.Created, ExecutionState.Initializing, Commands.Init);
22 Edge(ExecutionState.Created, ExecutionState.Disposed, Commands.Dispose);
23 Edge(ExecutionState.Created, ExecutionState.Disposed, Commands.Dispose);
23
24
24 Edge(ExecutionState.Initializing, ExecutionState.Ready, Commands.Ok);
25 Edge(ExecutionState.Initializing, ExecutionState.Ready, Commands.Ok);
25 Edge(ExecutionState.Initializing, ExecutionState.Failed, Commands.Fail);
26 Edge(ExecutionState.Initializing, ExecutionState.Failed, Commands.Fail);
26
27
27 Edge(ExecutionState.Ready, ExecutionState.Starting, Commands.Start);
28 Edge(ExecutionState.Ready, ExecutionState.Starting, Commands.Start);
28 Edge(ExecutionState.Ready, ExecutionState.Disposed, Commands.Dispose);
29 Edge(ExecutionState.Ready, ExecutionState.Disposed, Commands.Dispose);
29
30
30 Edge(ExecutionState.Starting, ExecutionState.Running, Commands.Ok);
31 Edge(ExecutionState.Starting, ExecutionState.Running, Commands.Ok);
31 Edge(ExecutionState.Starting, ExecutionState.Failed, Commands.Fail);
32 Edge(ExecutionState.Starting, ExecutionState.Failed, Commands.Fail);
32 Edge(ExecutionState.Starting, ExecutionState.Stopping, Commands.Stop);
33 Edge(ExecutionState.Starting, ExecutionState.Stopping, Commands.Stop);
33 Edge(ExecutionState.Starting, ExecutionState.Disposed, Commands.Dispose);
34 Edge(ExecutionState.Starting, ExecutionState.Disposed, Commands.Dispose);
34
35
35 Edge(ExecutionState.Running, ExecutionState.Failed, Commands.Fail);
36 Edge(ExecutionState.Running, ExecutionState.Failed, Commands.Fail);
36 Edge(ExecutionState.Running, ExecutionState.Stopping, Commands.Stop);
37 Edge(ExecutionState.Running, ExecutionState.Stopping, Commands.Stop);
37 Edge(ExecutionState.Running, ExecutionState.Disposed, Commands.Dispose);
38 Edge(ExecutionState.Running, ExecutionState.Disposed, Commands.Dispose);
38
39
39 Edge(ExecutionState.Stopping, ExecutionState.Failed, Commands.Fail);
40 Edge(ExecutionState.Stopping, ExecutionState.Failed, Commands.Fail);
40 Edge(ExecutionState.Stopping, ExecutionState.Disposed, Commands.Ok);
41 Edge(ExecutionState.Stopping, ExecutionState.Ready, Commands.Ok);
42 Edge(ExecutionState.Stopping, ExecutionState.Disposed, Commands.Dispose);
41
43
42 Edge(ExecutionState.Failed, ExecutionState.Disposed, Commands.Dispose);
44 Edge(ExecutionState.Failed, ExecutionState.Disposed, Commands.Dispose);
45 Edge(ExecutionState.Failed, ExecutionState.Initializing, Commands.Reset);
43 }
46 }
44
47
45 static void Edge(ExecutionState s1, ExecutionState s2, Commands cmd) {
48 static void Edge(ExecutionState s1, ExecutionState s2, Commands cmd) {
46 _transitions[(int)s1, (int)cmd] = s2;
49 _transitions[(int)s1, (int)cmd] = s2;
47 }
50 }
48
51
49 public ExecutionState State {
52 public ExecutionState State {
50 get;
53 get;
51 private set;
54 private set;
52 }
55 }
53
56
54 public StateMachine(ExecutionState initial) {
57 public StateMachine(ExecutionState initial) {
55 State = initial;
58 State = initial;
56 }
59 }
57
60
58 public bool Move(Commands cmd) {
61 public bool Move(Commands cmd) {
59 var next = _transitions[(int)State, (int)cmd];
62 var next = _transitions[(int)State, (int)cmd];
60 if (next == ExecutionState.Undefined)
63 if (next == ExecutionState.Undefined)
61 return false;
64 return false;
62 State = next;
65 State = next;
63 return true;
66 return true;
64 }
67 }
65 }
68 }
66
69
67 IPromise m_pending;
70 IPromise m_pending;
68 Exception m_lastError;
71 Exception m_lastError;
69
72
70 readonly StateMachine m_stateMachine;
73 readonly StateMachine m_stateMachine;
74 readonly bool m_reusable;
75 public event EventHandler<StateChangeEventArgs> StateChanged;
71
76
72 protected RunnableComponent(bool initialized) {
77 /// <summary>
78 /// Initializes component state.
79 /// </summary>
80 /// <param name="initialized">If set, the component initial state is <see cref="ExecutionState.Ready"/> and the component is ready to start, otherwise initialization is required.</param>
81 /// <param name="reusable">If set, the component may start after it has been stopped, otherwise the component is disposed after being stopped.</param>
82 protected RunnableComponent(bool initialized, bool reusable) {
73 m_stateMachine = new StateMachine(initialized ? ExecutionState.Ready : ExecutionState.Created);
83 m_stateMachine = new StateMachine(initialized ? ExecutionState.Ready : ExecutionState.Created);
84 m_reusable = reusable;
74 DisposeTimeout = 10000;
85 DisposeTimeout = 10000;
75 }
86 }
76
87
77 /// <summary>
88 /// <summary>
89 /// Initializes component state. The component created with this constructor is not reusable, i.e. it will be disposed after stop.
90 /// </summary>
91 /// <param name="initialized">If set, the component initial state is <see cref="ExecutionState.Ready"/> and the component is ready to start, otherwise initialization is required.</param>
92 protected RunnableComponent(bool initialized) : this(initialized, false) {
93 }
94
95 /// <summary>
78 /// Gets or sets the timeout to wait for the pending operation to complete. If the pending operation doesn't finish than the component will be disposed anyway.
96 /// Gets or sets the timeout to wait for the pending operation to complete. If the pending operation doesn't finish than the component will be disposed anyway.
79 /// </summary>
97 /// </summary>
80 protected int DisposeTimeout {
98 protected int DisposeTimeout {
81 get;
99 get;
82 set;
100 set;
83 }
101 }
84
102
85 void ThrowInvalidCommand(Commands cmd) {
103 void ThrowInvalidCommand(Commands cmd) {
86 if (m_stateMachine.State == ExecutionState.Disposed)
104 if (m_stateMachine.State == ExecutionState.Disposed)
87 throw new ObjectDisposedException(ToString());
105 throw new ObjectDisposedException(ToString());
88
106
89 throw new InvalidOperationException(String.Format("Commnd {0} is not allowed in the state {1}", cmd, m_stateMachine.State));
107 throw new InvalidOperationException(String.Format("Command {0} is not allowed in the state {1}", cmd, m_stateMachine.State));
108 }
109
110 bool MoveIfInState(Commands cmd, IPromise pending, Exception error, ExecutionState state) {
111 ExecutionState prev, current;
112 lock (m_stateMachine) {
113 if (m_stateMachine.State != state)
114 return false;
115
116 prev = m_stateMachine.State;
117 if (!m_stateMachine.Move(cmd))
118 ThrowInvalidCommand(cmd);
119 current = m_stateMachine.State;
120
121 m_pending = pending;
122 m_lastError = error;
123 }
124 if (prev != current)
125 OnStateChanged(prev, current, error);
126 return true;
90 }
127 }
91
128
92 void Move(Commands cmd) {
129 bool MoveIfPending(Commands cmd, IPromise pending, Exception error, IPromise expected) {
130 ExecutionState prev, current;
131 lock (m_stateMachine) {
132 if (m_pending != expected)
133 return false;
134 prev = m_stateMachine.State;
93 if (!m_stateMachine.Move(cmd))
135 if (!m_stateMachine.Move(cmd))
94 ThrowInvalidCommand(cmd);
136 ThrowInvalidCommand(cmd);
137 current = m_stateMachine.State;
138 m_pending = pending;
139 m_lastError = error;
140 }
141 if (prev != current)
142 OnStateChanged(prev, current, error);
143 return true;
144 }
145
146 IPromise Move(Commands cmd, IPromise pending, Exception error) {
147 ExecutionState prev, current;
148 IPromise ret;
149 lock (m_stateMachine) {
150 prev = m_stateMachine.State;
151 if (!m_stateMachine.Move(cmd))
152 ThrowInvalidCommand(cmd);
153 current = m_stateMachine.State;
154
155 ret = m_pending;
156 m_pending = pending;
157 m_lastError = error;
158
159 }
160 if(prev != current)
161 OnStateChanged(prev, current, error);
162 return ret;
163 }
164
165 protected virtual void OnStateChanged(ExecutionState previous, ExecutionState current, Exception error) {
166 var h = StateChanged;
167 if (h != null)
168 h(this, new StateChangeEventArgs {
169 State = current,
170 LastError = error
171 });
95 }
172 }
96
173
97 /// <summary>
174 /// <summary>
98 /// Moves the component from running to failed state.
175 /// Moves the component from running to failed state.
99 /// </summary>
176 /// </summary>
100 /// <param name="error">The exception which is describing the error.</param>
177 /// <param name="error">The exception which is describing the error.</param>
101 /// <returns>Returns true if the component is set to the failed state, false - otherwise.
102 /// This method works only for the running state, in any other state it will return false.</returns>
103 protected bool Fail(Exception error) {
178 protected bool Fail(Exception error) {
104 lock (m_stateMachine) {
179 return MoveIfInState(Commands.Fail, null, error, ExecutionState.Running);
105 if(m_stateMachine.State == ExecutionState.Running) {
106 m_stateMachine.Move(Commands.Fail);
107 m_lastError = error;
108 return true;
109 }
110 }
111 return false;
112 }
180 }
113
181
114 void Invoke(Commands cmd, Action action) {
182 /// <summary>
115 lock (m_stateMachine)
183 /// Tries to reset <see cref="ExecutionState.Failed"/> state to <see cref="ExecutionState.Ready"/>.
116 Move(cmd);
184 /// </summary>
185 /// <returns>True if component is reset to <see cref="ExecutionState.Ready"/>, false if the componet wasn't
186 /// in <see cref="ExecutionState.Failed"/> state.</returns>
187 /// <remarks>
188 /// This method checks the current state of the component and if it's in <see cref="ExecutionState.Failed"/>
189 /// moves component to <see cref="ExecutionState.Initializing"/>.
190 /// The <see cref="OnResetState()"/> is called and if this method completes succesfully the component moved
191 /// to <see cref="ExecutionState.Ready"/> state, otherwise the component is moved to <see cref="ExecutionState.Failed"/>
192 /// state. If <see cref="OnResetState()"/> throws an exception it will be propagated by this method to the caller.
193 /// </remarks>
194 protected bool ResetState() {
195 if (!MoveIfInState(Commands.Reset, null, null, ExecutionState.Failed))
196 return false;
117
197
118 try {
198 try {
119 action();
199 OnResetState();
120 lock(m_stateMachine)
200 Move(Commands.Ok, null, null);
121 Move(Commands.Ok);
201 return true;
122
123 } catch (Exception err) {
202 } catch (Exception err) {
124 lock (m_stateMachine) {
203 Move(Commands.Fail, null, err);
125 Move(Commands.Fail);
126 m_lastError = err;
127 }
128 throw;
204 throw;
129 }
205 }
130 }
206 }
131
207
208 /// <summary>
209 /// This method is called by <see cref="ResetState"/> to reinitialize component in the failed state.
210 /// </summary>
211 /// <remarks>
212 /// Default implementation throws <see cref="NotImplementedException"/> which will cause the component
213 /// fail to reset it's state and it left in <see cref="ExecutionState.Failed"/> state.
214 /// If this method doesn't throw exceptions the component is moved to <see cref="ExecutionState.Ready"/> state.
215 /// </remarks>
216 protected virtual void OnResetState() {
217 throw new NotImplementedException();
218 }
219
132 IPromise InvokeAsync(Commands cmd, Func<IPromise> action, Action<IPromise, IDeferred> chain) {
220 IPromise InvokeAsync(Commands cmd, Func<IPromise> action, Action<IPromise, IDeferred> chain) {
133 IPromise promise = null;
221 IPromise promise = null;
134 IPromise prev;
222 IPromise prev;
135
223
136 var task = new ActionChainTask(action, null, null, true);
224 var task = new ActionChainTask(action, null, null, true);
137
225
138 lock (m_stateMachine) {
139 Move(cmd);
140
141 prev = m_pending;
142
143 Action<Exception> errorOrCancel = e => {
226 Action<Exception> errorOrCancel = e => {
144 if (e == null)
227 if (e == null)
145 e = new OperationCanceledException();
228 e = new OperationCanceledException();
146
229 MoveIfPending(Commands.Fail, null, e, promise);
147 lock (m_stateMachine) {
148 if (m_pending == promise) {
149 Move(Commands.Fail);
150 m_pending = null;
151 m_lastError = e;
152 }
153 }
154 throw new PromiseTransientException(e);
230 throw new PromiseTransientException(e);
155 };
231 };
156
232
157 promise = task.Then(
233 promise = task.Then(
158 () => {
234 () => MoveIfPending(Commands.Ok, null, null, promise),
159 lock(m_stateMachine) {
160 if (m_pending == promise) {
161 Move(Commands.Ok);
162 m_pending = null;
163 }
164 }
165 },
166 errorOrCancel,
235 errorOrCancel,
167 errorOrCancel
236 errorOrCancel
168 );
237 );
169
238
170 m_pending = promise;
239 prev = Move(cmd, promise, null);
171 }
172
240
173 if (prev == null)
241 if (prev == null)
174 task.Resolve();
242 task.Resolve();
175 else
243 else
176 chain(prev, task);
244 chain(prev, task);
177
245
178 return promise;
246 return promise;
179 }
247 }
180
248
181
249
182 #region IInitializable implementation
250 #region IInitializable implementation
183
251
184 public void Init() {
252 public void Initialize() {
185 Invoke(Commands.Init, OnInitialize);
253 Move(Commands.Init, null, null);
254
255 try {
256 OnInitialize();
257 Move(Commands.Ok, null, null);
258 } catch (Exception err) {
259 Move(Commands.Fail, null, err);
260 throw;
261 }
186 }
262 }
187
263
188 protected virtual void OnInitialize() {
264 protected virtual void OnInitialize() {
189 }
265 }
190
266
191 #endregion
267 #endregion
192
268
193 #region IRunnable implementation
269 #region IRunnable implementation
194
270
195 public IPromise Start() {
271 public IPromise Start() {
196 return InvokeAsync(Commands.Start, OnStart, null);
272 return InvokeAsync(Commands.Start, OnStart, null);
197 }
273 }
198
274
199 protected virtual IPromise OnStart() {
275 protected virtual IPromise OnStart() {
200 return Promise.SUCCESS;
276 return Promise.Success;
201 }
277 }
202
278
203 public IPromise Stop() {
279 public IPromise Stop() {
204 return InvokeAsync(Commands.Stop, OnStop, StopPending).Then(Dispose);
280 var pending = InvokeAsync(Commands.Stop, OnStop, StopPending);
281 return m_reusable ? pending : pending.Then(Dispose);
205 }
282 }
206
283
207 protected virtual IPromise OnStop() {
284 protected virtual IPromise OnStop() {
208 return Promise.SUCCESS;
285 return Promise.Success;
209 }
286 }
210
287
211 /// <summary>
288 /// <summary>
212 /// Stops the current operation if one exists.
289 /// Stops the current operation if one exists.
213 /// </summary>
290 /// </summary>
214 /// <param name="current">Current.</param>
291 /// <param name="current">Current.</param>
215 /// <param name="stop">Stop.</param>
292 /// <param name="stop">Stop.</param>
216 protected virtual void StopPending(IPromise current, IDeferred stop) {
293 protected virtual void StopPending(IPromise current, IDeferred stop) {
217 if (current == null) {
294 if (current == null) {
218 stop.Resolve();
295 stop.Resolve();
219 } else {
296 } else {
220 // связваем текущую операцию с операцией остановки
297 // связваем текущую операцию с операцией остановки
221 current.On(
298 current.On(
222 stop.Resolve, // если текущая операция заверщилась, то можно начинать остановку
299 stop.Resolve, // если текущая операция заверщилась, то можно начинать остановку
223 stop.Reject, // если текущая операция дала ошибку - то все плохо, нельзя продолжать
300 stop.Reject, // если текущая операция дала ошибку - то все плохо, нельзя продолжать
224 e => stop.Resolve() // если текущая отменилась, то можно начинать остановку
301 e => stop.Resolve() // если текущая отменилась, то можно начинать остановку
225 );
302 );
226 // посылаем текущей операции сигнал остановки
303 // посылаем текущей операции сигнал остановки
227 current.Cancel();
304 current.Cancel();
228 }
305 }
229 }
306 }
230
307
231 public ExecutionState State {
308 public ExecutionState State {
232 get {
309 get {
233 return m_stateMachine.State;
310 return m_stateMachine.State;
234 }
311 }
235 }
312 }
236
313
237 public Exception LastError {
314 public Exception LastError {
238 get {
315 get {
239 return m_lastError;
316 return m_lastError;
240 }
317 }
241 }
318 }
242
319
243 #endregion
320 #endregion
244
321
245 #region IDisposable implementation
322 #region IDisposable implementation
246
323
247 /// <summary>
324 /// <summary>
248 /// Releases all resource used by the <see cref="Implab.Components.RunnableComponent"/> object.
325 /// Releases all resource used by the <see cref="Implab.Components.RunnableComponent"/> object.
249 /// </summary>
326 /// </summary>
250 /// <remarks>
327 /// <remarks>
251 /// <para>Will not try to stop the component, it will just release all resources.
328 /// <para>Will not try to stop the component, it will just release all resources.
252 /// To cleanup the component gracefully use <see cref="Stop()"/> method.</para>
329 /// To cleanup the component gracefully use <see cref="Stop()"/> method.</para>
253 /// <para>
330 /// <para>
254 /// In normal cases the <see cref="Dispose()"/> method shouldn't be called, the call to the <see cref="Stop()"/>
331 /// In normal cases the <see cref="Dispose()"/> method shouldn't be called, the call to the <see cref="Stop()"/>
255 /// method is sufficient to cleanup the component. Call <see cref="Dispose()"/> only to cleanup after errors,
332 /// method is sufficient to cleanup the component. Call <see cref="Dispose()"/> only to cleanup after errors,
256 /// especially if <see cref="Stop"/> method is failed. Using this method insted of <see cref="Stop()"/> may
333 /// especially if <see cref="Stop"/> method is failed. Using this method insted of <see cref="Stop()"/> may
257 /// lead to the data loss by the component.
334 /// lead to the data loss by the component.
258 /// </para></remarks>
335 /// </para></remarks>
259 public void Dispose() {
336 public void Dispose() {
260 IPromise pending;
337 IPromise pending;
338
261 lock (m_stateMachine) {
339 lock (m_stateMachine) {
262 if (m_stateMachine.State == ExecutionState.Disposed)
340 if (m_stateMachine.State == ExecutionState.Disposed)
263 return;
341 return;
264
342 pending = Move(Commands.Dispose, null, null);
265 Move(Commands.Dispose);
343 }
266
344
267 GC.SuppressFinalize(this);
345 GC.SuppressFinalize(this);
268
269 pending = m_pending;
270 m_pending = null;
271 }
272 if (pending != null) {
346 if (pending != null) {
273 pending.Cancel();
347 pending.Cancel();
274 pending.Timeout(DisposeTimeout).On(
348 pending.Timeout(DisposeTimeout).On(
275 () => Dispose(true, null),
349 () => Dispose(true, null),
276 err => Dispose(true, err),
350 err => Dispose(true, err),
277 reason => Dispose(true, new OperationCanceledException("The operation is cancelled", reason))
351 reason => Dispose(true, new OperationCanceledException("The operation is cancelled", reason))
278 );
352 );
279 } else {
353 } else {
280 Dispose(true, m_lastError);
354 Dispose(true, null);
281 }
355 }
282 }
356 }
283
357
284 ~RunnableComponent() {
358 ~RunnableComponent() {
285 Dispose(false, null);
359 Dispose(false, null);
286 }
360 }
287
361
288 #endregion
362 #endregion
289
363
364 /// <summary>
365 /// Releases all resources used by the component, called automatically, override this method to implement your cleanup.
366 /// </summary>
367 /// <param name="disposing">true if this method is called during normal dispose process.</param>
368 /// <param name="lastError">The last error which occured during the component stop.</param>
290 protected virtual void Dispose(bool disposing, Exception lastError) {
369 protected virtual void Dispose(bool disposing, Exception lastError) {
291
370
292 }
371 }
293
372
294 }
373 }
295 }
374 }
296
375
@@ -1,46 +1,47
1 using System;
1 using System;
2 using System.IO;
2 using System.IO;
3 using System.Text;
3 using System.Text;
4
4
5 namespace Implab.Diagnostics {
5 namespace Implab.Diagnostics {
6 public class TextFileListener: ListenerBase {
6 public class TextFileListener: ListenerBase {
7 readonly TextWriter m_textWriter;
7 readonly TextWriter m_textWriter;
8 readonly object m_lock = new object();
8
9
9 public TextFileListener(string fileName) {
10 public TextFileListener(string fileName) {
10 m_textWriter = File.CreateText(fileName);
11 m_textWriter = File.CreateText(fileName);
11
12
12 m_textWriter.WriteLine("LOG {0}", DateTime.Now);
13 m_textWriter.WriteLine("LOG {0}", DateTime.Now);
13 }
14 }
14
15
15 #region implemented abstract members of ListenerBase
16 #region implemented abstract members of ListenerBase
16
17
17 public override void Write(LogEventArgs args, object entry) {
18 public override void Write(LogEventArgs args, object entry) {
18 var msg = new StringBuilder();
19 var msg = new StringBuilder();
19 for (int i = 0; i < args.Operation.Level; i++)
20 for (int i = 0; i < args.Operation.Level; i++)
20 msg.Append(" ");
21 msg.Append(" ");
21 msg.AppendFormat("[{0}]:{1}: {2}", args.ThreadId, args.Channel, entry);
22 msg.AppendFormat("[{0}]:{1}: {2}", args.ThreadId, args.Channel, entry);
22
23
23 lock (m_textWriter) {
24 lock (m_lock) {
24 if (!IsDisposed) {
25 if (!IsDisposed) {
25 // тут гарантировано еще не освобожден m_textWriter
26 // тут гарантировано еще не освобожден m_textWriter
26 m_textWriter.WriteLine(msg);
27 m_textWriter.WriteLine(msg);
27 m_textWriter.Flush();
28 m_textWriter.Flush();
28 }
29 }
29 }
30 }
30 }
31 }
31
32
32 #endregion
33 #endregion
33
34
34 protected override void Dispose(bool disposing) {
35 protected override void Dispose(bool disposing) {
35 base.Dispose(disposing);
36 base.Dispose(disposing);
36 if (disposing) {
37 if (disposing) {
37 // IsDisposed = true
38 // IsDisposed = true
38 lock (m_textWriter) {
39 lock (m_lock) {
39 Safe.Dispose(m_textWriter);
40 Safe.Dispose(m_textWriter);
40 }
41 }
41 }
42 }
42 }
43 }
43
44
44
45
45 }
46 }
46 }
47 }
@@ -1,278 +1,274
1 <?xml version="1.0" encoding="utf-8"?>
1 <?xml version="1.0" encoding="utf-8"?>
2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <PropertyGroup>
3 <PropertyGroup>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6 <ProjectGuid>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</ProjectGuid>
6 <ProjectGuid>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</ProjectGuid>
7 <OutputType>Library</OutputType>
7 <OutputType>Library</OutputType>
8 <RootNamespace>Implab</RootNamespace>
8 <RootNamespace>Implab</RootNamespace>
9 <AssemblyName>Implab</AssemblyName>
9 <AssemblyName>Implab</AssemblyName>
10 <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
10 <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
11 <ReleaseVersion>0.2</ReleaseVersion>
11 <ReleaseVersion>0.2</ReleaseVersion>
12 <ProductVersion>8.0.30703</ProductVersion>
12 <ProductVersion>8.0.30703</ProductVersion>
13 <SchemaVersion>2.0</SchemaVersion>
13 <SchemaVersion>2.0</SchemaVersion>
14 </PropertyGroup>
14 </PropertyGroup>
15 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
15 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
16 <DebugSymbols>true</DebugSymbols>
16 <DebugSymbols>true</DebugSymbols>
17 <DebugType>full</DebugType>
17 <DebugType>full</DebugType>
18 <Optimize>false</Optimize>
18 <Optimize>false</Optimize>
19 <OutputPath>bin\Debug</OutputPath>
19 <OutputPath>bin\Debug</OutputPath>
20 <DefineConstants>TRACE;DEBUG;</DefineConstants>
20 <DefineConstants>TRACE;DEBUG;</DefineConstants>
21 <ErrorReport>prompt</ErrorReport>
21 <ErrorReport>prompt</ErrorReport>
22 <WarningLevel>4</WarningLevel>
22 <WarningLevel>4</WarningLevel>
23 <ConsolePause>false</ConsolePause>
23 <ConsolePause>false</ConsolePause>
24 <RunCodeAnalysis>true</RunCodeAnalysis>
24 <RunCodeAnalysis>true</RunCodeAnalysis>
25 </PropertyGroup>
25 </PropertyGroup>
26 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
26 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
27 <DebugType>full</DebugType>
27 <DebugType>full</DebugType>
28 <Optimize>true</Optimize>
28 <Optimize>true</Optimize>
29 <OutputPath>bin\Release</OutputPath>
29 <OutputPath>bin\Release</OutputPath>
30 <ErrorReport>prompt</ErrorReport>
30 <ErrorReport>prompt</ErrorReport>
31 <WarningLevel>4</WarningLevel>
31 <WarningLevel>4</WarningLevel>
32 <ConsolePause>false</ConsolePause>
32 <ConsolePause>false</ConsolePause>
33 </PropertyGroup>
33 </PropertyGroup>
34 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' ">
34 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' ">
35 <DebugSymbols>true</DebugSymbols>
35 <DebugSymbols>true</DebugSymbols>
36 <DebugType>full</DebugType>
36 <DebugType>full</DebugType>
37 <Optimize>false</Optimize>
37 <Optimize>false</Optimize>
38 <OutputPath>bin\Debug</OutputPath>
38 <OutputPath>bin\Debug</OutputPath>
39 <DefineConstants>TRACE;DEBUG;NET_4_5</DefineConstants>
39 <DefineConstants>TRACE;DEBUG;NET_4_5</DefineConstants>
40 <ErrorReport>prompt</ErrorReport>
40 <ErrorReport>prompt</ErrorReport>
41 <WarningLevel>4</WarningLevel>
41 <WarningLevel>4</WarningLevel>
42 <RunCodeAnalysis>true</RunCodeAnalysis>
42 <RunCodeAnalysis>true</RunCodeAnalysis>
43 <ConsolePause>false</ConsolePause>
43 <ConsolePause>false</ConsolePause>
44 </PropertyGroup>
44 </PropertyGroup>
45 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' ">
45 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' ">
46 <Optimize>true</Optimize>
46 <Optimize>true</Optimize>
47 <OutputPath>bin\Release</OutputPath>
47 <OutputPath>bin\Release</OutputPath>
48 <ErrorReport>prompt</ErrorReport>
48 <ErrorReport>prompt</ErrorReport>
49 <WarningLevel>4</WarningLevel>
49 <WarningLevel>4</WarningLevel>
50 <ConsolePause>false</ConsolePause>
50 <ConsolePause>false</ConsolePause>
51 <DefineConstants>NET_4_5</DefineConstants>
51 <DefineConstants>NET_4_5</DefineConstants>
52 </PropertyGroup>
52 </PropertyGroup>
53 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugMono|AnyCPU' ">
53 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugMono|AnyCPU' ">
54 <DebugSymbols>true</DebugSymbols>
54 <DebugSymbols>true</DebugSymbols>
55 <DebugType>full</DebugType>
55 <DebugType>full</DebugType>
56 <Optimize>false</Optimize>
56 <Optimize>false</Optimize>
57 <OutputPath>bin\Debug</OutputPath>
57 <OutputPath>bin\Debug</OutputPath>
58 <DefineConstants>TRACE;DEBUG;NET_4_5;MONO</DefineConstants>
58 <DefineConstants>TRACE;DEBUG;NET_4_5;MONO</DefineConstants>
59 <ErrorReport>prompt</ErrorReport>
59 <ErrorReport>prompt</ErrorReport>
60 <WarningLevel>4</WarningLevel>
60 <WarningLevel>4</WarningLevel>
61 <RunCodeAnalysis>true</RunCodeAnalysis>
61 <RunCodeAnalysis>true</RunCodeAnalysis>
62 <ConsolePause>false</ConsolePause>
62 <ConsolePause>false</ConsolePause>
63 </PropertyGroup>
63 </PropertyGroup>
64 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseMono|AnyCPU' ">
64 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseMono|AnyCPU' ">
65 <Optimize>true</Optimize>
65 <Optimize>true</Optimize>
66 <OutputPath>bin\Release</OutputPath>
66 <OutputPath>bin\Release</OutputPath>
67 <DefineConstants>NET_4_5;MONO;</DefineConstants>
67 <DefineConstants>NET_4_5;MONO;</DefineConstants>
68 <ErrorReport>prompt</ErrorReport>
68 <ErrorReport>prompt</ErrorReport>
69 <WarningLevel>4</WarningLevel>
69 <WarningLevel>4</WarningLevel>
70 <ConsolePause>false</ConsolePause>
70 <ConsolePause>false</ConsolePause>
71 </PropertyGroup>
71 </PropertyGroup>
72 <ItemGroup>
72 <ItemGroup>
73 <Reference Include="System" />
73 <Reference Include="System" />
74 <Reference Include="System.Xml" />
74 <Reference Include="System.Xml" />
75 <Reference Include="mscorlib" />
75 <Reference Include="mscorlib" />
76 </ItemGroup>
76 </ItemGroup>
77 <ItemGroup>
77 <ItemGroup>
78 <Compile Include="Components\StateChangeEventArgs.cs" />
78 <Compile Include="CustomEqualityComparer.cs" />
79 <Compile Include="CustomEqualityComparer.cs" />
79 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
80 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
80 <Compile Include="Diagnostics\LogChannel.cs" />
81 <Compile Include="Diagnostics\LogChannel.cs" />
81 <Compile Include="Diagnostics\LogicalOperation.cs" />
82 <Compile Include="Diagnostics\LogicalOperation.cs" />
82 <Compile Include="Diagnostics\TextFileListener.cs" />
83 <Compile Include="Diagnostics\TextFileListener.cs" />
83 <Compile Include="Diagnostics\TraceLog.cs" />
84 <Compile Include="Diagnostics\TraceLog.cs" />
84 <Compile Include="Diagnostics\TraceEvent.cs" />
85 <Compile Include="Diagnostics\TraceEvent.cs" />
85 <Compile Include="Diagnostics\TraceEventType.cs" />
86 <Compile Include="Diagnostics\TraceEventType.cs" />
86 <Compile Include="ICancellable.cs" />
87 <Compile Include="ICancellable.cs" />
87 <Compile Include="IProgressHandler.cs" />
88 <Compile Include="IProgressHandler.cs" />
88 <Compile Include="IProgressNotifier.cs" />
89 <Compile Include="IProgressNotifier.cs" />
89 <Compile Include="IPromiseT.cs" />
90 <Compile Include="IPromiseT.cs" />
90 <Compile Include="IPromise.cs" />
91 <Compile Include="IPromise.cs" />
91 <Compile Include="IServiceLocator.cs" />
92 <Compile Include="IServiceLocator.cs" />
92 <Compile Include="ITaskController.cs" />
93 <Compile Include="ITaskController.cs" />
93 <Compile Include="Parallels\DispatchPool.cs" />
94 <Compile Include="Parallels\DispatchPool.cs" />
94 <Compile Include="Parallels\ArrayTraits.cs" />
95 <Compile Include="Parallels\ArrayTraits.cs" />
95 <Compile Include="Parallels\MTQueue.cs" />
96 <Compile Include="Parallels\MTQueue.cs" />
96 <Compile Include="Parallels\WorkerPool.cs" />
97 <Compile Include="Parallels\WorkerPool.cs" />
97 <Compile Include="ProgressInitEventArgs.cs" />
98 <Compile Include="ProgressInitEventArgs.cs" />
98 <Compile Include="Properties\AssemblyInfo.cs" />
99 <Compile Include="Properties\AssemblyInfo.cs" />
99 <Compile Include="Parallels\AsyncPool.cs" />
100 <Compile Include="Parallels\AsyncPool.cs" />
100 <Compile Include="Safe.cs" />
101 <Compile Include="Safe.cs" />
101 <Compile Include="ValueEventArgs.cs" />
102 <Compile Include="ValueEventArgs.cs" />
102 <Compile Include="PromiseExtensions.cs" />
103 <Compile Include="PromiseExtensions.cs" />
103 <Compile Include="SyncContextPromise.cs" />
104 <Compile Include="SyncContextPromise.cs" />
104 <Compile Include="Diagnostics\OperationContext.cs" />
105 <Compile Include="Diagnostics\OperationContext.cs" />
105 <Compile Include="Diagnostics\TraceContext.cs" />
106 <Compile Include="Diagnostics\TraceContext.cs" />
106 <Compile Include="Diagnostics\LogEventArgs.cs" />
107 <Compile Include="Diagnostics\LogEventArgs.cs" />
107 <Compile Include="Diagnostics\LogEventArgsT.cs" />
108 <Compile Include="Diagnostics\LogEventArgsT.cs" />
108 <Compile Include="Diagnostics\Extensions.cs" />
109 <Compile Include="Diagnostics\Extensions.cs" />
109 <Compile Include="PromiseEventType.cs" />
110 <Compile Include="PromiseEventType.cs" />
110 <Compile Include="Parallels\AsyncQueue.cs" />
111 <Compile Include="Parallels\AsyncQueue.cs" />
111 <Compile Include="PromiseT.cs" />
112 <Compile Include="PromiseT.cs" />
112 <Compile Include="IDeferred.cs" />
113 <Compile Include="IDeferred.cs" />
113 <Compile Include="IDeferredT.cs" />
114 <Compile Include="IDeferredT.cs" />
114 <Compile Include="Promise.cs" />
115 <Compile Include="Promise.cs" />
115 <Compile Include="PromiseTransientException.cs" />
116 <Compile Include="PromiseTransientException.cs" />
116 <Compile Include="Parallels\Signal.cs" />
117 <Compile Include="Parallels\Signal.cs" />
117 <Compile Include="Parallels\SharedLock.cs" />
118 <Compile Include="Parallels\SharedLock.cs" />
118 <Compile Include="Diagnostics\ILogWriter.cs" />
119 <Compile Include="Diagnostics\ILogWriter.cs" />
119 <Compile Include="Diagnostics\ListenerBase.cs" />
120 <Compile Include="Diagnostics\ListenerBase.cs" />
120 <Compile Include="Parallels\BlockingQueue.cs" />
121 <Compile Include="Parallels\BlockingQueue.cs" />
121 <Compile Include="AbstractEvent.cs" />
122 <Compile Include="AbstractEvent.cs" />
122 <Compile Include="AbstractPromise.cs" />
123 <Compile Include="AbstractPromise.cs" />
123 <Compile Include="AbstractPromiseT.cs" />
124 <Compile Include="AbstractPromiseT.cs" />
124 <Compile Include="FuncTask.cs" />
125 <Compile Include="FuncTask.cs" />
125 <Compile Include="FuncTaskBase.cs" />
126 <Compile Include="FuncTaskBase.cs" />
126 <Compile Include="FuncTaskT.cs" />
127 <Compile Include="FuncTaskT.cs" />
127 <Compile Include="ActionChainTaskBase.cs" />
128 <Compile Include="ActionChainTaskBase.cs" />
128 <Compile Include="ActionChainTask.cs" />
129 <Compile Include="ActionChainTask.cs" />
129 <Compile Include="ActionChainTaskT.cs" />
130 <Compile Include="ActionChainTaskT.cs" />
130 <Compile Include="FuncChainTaskBase.cs" />
131 <Compile Include="FuncChainTaskBase.cs" />
131 <Compile Include="FuncChainTask.cs" />
132 <Compile Include="FuncChainTask.cs" />
132 <Compile Include="FuncChainTaskT.cs" />
133 <Compile Include="FuncChainTaskT.cs" />
133 <Compile Include="ActionTaskBase.cs" />
134 <Compile Include="ActionTaskBase.cs" />
134 <Compile Include="ActionTask.cs" />
135 <Compile Include="ActionTask.cs" />
135 <Compile Include="ActionTaskT.cs" />
136 <Compile Include="ActionTaskT.cs" />
136 <Compile Include="ICancellationToken.cs" />
137 <Compile Include="ICancellationToken.cs" />
137 <Compile Include="SuccessPromise.cs" />
138 <Compile Include="SuccessPromise.cs" />
138 <Compile Include="SuccessPromiseT.cs" />
139 <Compile Include="SuccessPromiseT.cs" />
139 <Compile Include="PromiseAwaiterT.cs" />
140 <Compile Include="PromiseAwaiterT.cs" />
140 <Compile Include="PromiseAwaiter.cs" />
141 <Compile Include="PromiseAwaiter.cs" />
141 <Compile Include="Components\ComponentContainer.cs" />
142 <Compile Include="Components\ComponentContainer.cs" />
142 <Compile Include="Components\Disposable.cs" />
143 <Compile Include="Components\Disposable.cs" />
143 <Compile Include="Components\DisposablePool.cs" />
144 <Compile Include="Components\DisposablePool.cs" />
144 <Compile Include="Components\ObjectPool.cs" />
145 <Compile Include="Components\ObjectPool.cs" />
145 <Compile Include="Components\ServiceLocator.cs" />
146 <Compile Include="Components\ServiceLocator.cs" />
146 <Compile Include="Components\IInitializable.cs" />
147 <Compile Include="Components\IInitializable.cs" />
147 <Compile Include="TaskController.cs" />
148 <Compile Include="TaskController.cs" />
148 <Compile Include="Components\App.cs" />
149 <Compile Include="Components\App.cs" />
149 <Compile Include="Components\IRunnable.cs" />
150 <Compile Include="Components\IRunnable.cs" />
150 <Compile Include="Components\ExecutionState.cs" />
151 <Compile Include="Components\ExecutionState.cs" />
151 <Compile Include="Components\RunnableComponent.cs" />
152 <Compile Include="Components\RunnableComponent.cs" />
152 <Compile Include="Components\IFactory.cs" />
153 <Compile Include="Components\IFactory.cs" />
153 <Compile Include="Automaton\IAlphabet.cs" />
154 <Compile Include="Automaton\IAlphabet.cs" />
154 <Compile Include="Automaton\ParserException.cs" />
155 <Compile Include="Automaton\ParserException.cs" />
155 <Compile Include="Automaton\IndexedAlphabetBase.cs" />
156 <Compile Include="Automaton\IndexedAlphabetBase.cs" />
156 <Compile Include="Automaton\IAlphabetBuilder.cs" />
157 <Compile Include="Automaton\IAlphabetBuilder.cs" />
157 <Compile Include="Automaton\RegularExpressions\AltToken.cs" />
158 <Compile Include="Automaton\RegularExpressions\AltToken.cs" />
158 <Compile Include="Automaton\RegularExpressions\BinaryToken.cs" />
159 <Compile Include="Automaton\RegularExpressions\BinaryToken.cs" />
159 <Compile Include="Automaton\RegularExpressions\CatToken.cs" />
160 <Compile Include="Automaton\RegularExpressions\CatToken.cs" />
160 <Compile Include="Automaton\RegularExpressions\StarToken.cs" />
161 <Compile Include="Automaton\RegularExpressions\StarToken.cs" />
161 <Compile Include="Automaton\RegularExpressions\SymbolToken.cs" />
162 <Compile Include="Automaton\RegularExpressions\SymbolToken.cs" />
162 <Compile Include="Automaton\RegularExpressions\EmptyToken.cs" />
163 <Compile Include="Automaton\RegularExpressions\EmptyToken.cs" />
163 <Compile Include="Automaton\RegularExpressions\Token.cs" />
164 <Compile Include="Automaton\RegularExpressions\Token.cs" />
164 <Compile Include="Automaton\RegularExpressions\IVisitor.cs" />
165 <Compile Include="Automaton\RegularExpressions\IVisitor.cs" />
165 <Compile Include="Automaton\AutomatonTransition.cs" />
166 <Compile Include="Automaton\AutomatonTransition.cs" />
166 <Compile Include="Formats\JSON\JSONElementContext.cs" />
167 <Compile Include="Formats\JSON\JSONElementContext.cs" />
167 <Compile Include="Formats\JSON\JSONElementType.cs" />
168 <Compile Include="Formats\JSON\JSONElementType.cs" />
168 <Compile Include="Formats\JSON\JSONGrammar.cs" />
169 <Compile Include="Formats\JSON\JSONGrammar.cs" />
169 <Compile Include="Formats\JSON\JSONParser.cs" />
170 <Compile Include="Formats\JSON\JSONParser.cs" />
170 <Compile Include="Formats\JSON\JSONScanner.cs" />
171 <Compile Include="Formats\JSON\JSONScanner.cs" />
171 <Compile Include="Formats\JSON\JsonTokenType.cs" />
172 <Compile Include="Formats\JSON\JsonTokenType.cs" />
172 <Compile Include="Formats\JSON\JSONWriter.cs" />
173 <Compile Include="Formats\JSON\JSONWriter.cs" />
173 <Compile Include="Formats\JSON\JSONXmlReader.cs" />
174 <Compile Include="Formats\JSON\JSONXmlReader.cs" />
174 <Compile Include="Formats\JSON\JSONXmlReaderOptions.cs" />
175 <Compile Include="Formats\JSON\JSONXmlReaderOptions.cs" />
175 <Compile Include="Formats\JSON\StringTranslator.cs" />
176 <Compile Include="Formats\JSON\StringTranslator.cs" />
176 <Compile Include="Automaton\MapAlphabet.cs" />
177 <Compile Include="Automaton\MapAlphabet.cs" />
177 <Compile Include="Formats\CharAlphabet.cs" />
178 <Compile Include="Formats\CharAlphabet.cs" />
178 <Compile Include="Formats\ByteAlphabet.cs" />
179 <Compile Include="Formats\ByteAlphabet.cs" />
179 <Compile Include="Automaton\IDFATable.cs" />
180 <Compile Include="Automaton\IDFATable.cs" />
180 <Compile Include="Automaton\IDFATableBuilder.cs" />
181 <Compile Include="Automaton\IDFATableBuilder.cs" />
181 <Compile Include="Automaton\DFATable.cs" />
182 <Compile Include="Automaton\DFATable.cs" />
182 <Compile Include="Automaton\RegularExpressions\RegularExpressionVisitor.cs" />
183 <Compile Include="Automaton\RegularExpressions\RegularExpressionVisitor.cs" />
183 <Compile Include="Automaton\RegularExpressions\ITaggedDFABuilder.cs" />
184 <Compile Include="Automaton\RegularExpressions\ITaggedDFABuilder.cs" />
184 <Compile Include="Formats\TextScanner.cs" />
185 <Compile Include="Formats\TextScanner.cs" />
185 <Compile Include="Formats\StringScanner.cs" />
186 <Compile Include="Formats\StringScanner.cs" />
186 <Compile Include="Formats\ReaderScanner.cs" />
187 <Compile Include="Formats\ReaderScanner.cs" />
187 <Compile Include="Formats\ScannerContext.cs" />
188 <Compile Include="Formats\ScannerContext.cs" />
188 <Compile Include="Formats\Grammar.cs" />
189 <Compile Include="Formats\Grammar.cs" />
189 <Compile Include="Automaton\RegularExpressions\EndTokenT.cs" />
190 <Compile Include="Automaton\RegularExpressions\EndTokenT.cs" />
190 <Compile Include="Automaton\RegularExpressions\EndToken.cs" />
191 <Compile Include="Automaton\RegularExpressions\EndToken.cs" />
191 <Compile Include="Automaton\RegularExpressions\RegularExpressionVisitorT.cs" />
192 <Compile Include="Automaton\RegularExpressions\RegularExpressionVisitorT.cs" />
192 <Compile Include="Automaton\AutomatonConst.cs" />
193 <Compile Include="Automaton\AutomatonConst.cs" />
193 <Compile Include="Automaton\RegularExpressions\RegularDFA.cs" />
194 <Compile Include="Automaton\RegularExpressions\RegularDFA.cs" />
194 <Compile Include="Components\LazyAndWeak.cs" />
195 <Compile Include="Components\LazyAndWeak.cs" />
195 <Compile Include="AbstractTask.cs" />
196 <Compile Include="AbstractTask.cs" />
196 <Compile Include="AbstractTaskT.cs" />
197 <Compile Include="AbstractTaskT.cs" />
197 <Compile Include="FailedPromise.cs" />
198 <Compile Include="FailedPromise.cs" />
198 <Compile Include="FailedPromiseT.cs" />
199 <Compile Include="FailedPromiseT.cs" />
199 <Compile Include="Components\PollingComponent.cs" />
200 <Compile Include="Components\PollingComponent.cs" />
200 </ItemGroup>
201 </ItemGroup>
201 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
202 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
202 <ItemGroup />
203 <ItemGroup />
203 <ProjectExtensions>
204 <ProjectExtensions>
204 <MonoDevelop>
205 <MonoDevelop>
205 <Properties>
206 <Properties>
206 <Policies>
207 <Policies>
207 <CSharpFormattingPolicy IndentSwitchBody="True" NamespaceBraceStyle="EndOfLine" ClassBraceStyle="EndOfLine" InterfaceBraceStyle="EndOfLine" StructBraceStyle="EndOfLine" EnumBraceStyle="EndOfLine" MethodBraceStyle="EndOfLine" ConstructorBraceStyle="EndOfLine" DestructorBraceStyle="EndOfLine" BeforeMethodDeclarationParentheses="False" BeforeMethodCallParentheses="False" BeforeConstructorDeclarationParentheses="False" NewLineBeforeConstructorInitializerColon="NewLine" NewLineAfterConstructorInitializerColon="SameLine" BeforeIndexerDeclarationBracket="False" BeforeDelegateDeclarationParentheses="False" NewParentheses="False" SpacesBeforeBrackets="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
208 <CSharpFormattingPolicy IndentSwitchBody="True" NamespaceBraceStyle="EndOfLine" ClassBraceStyle="EndOfLine" InterfaceBraceStyle="EndOfLine" StructBraceStyle="EndOfLine" EnumBraceStyle="EndOfLine" MethodBraceStyle="EndOfLine" ConstructorBraceStyle="EndOfLine" DestructorBraceStyle="EndOfLine" BeforeMethodDeclarationParentheses="False" BeforeMethodCallParentheses="False" BeforeConstructorDeclarationParentheses="False" NewLineBeforeConstructorInitializerColon="NewLine" NewLineAfterConstructorInitializerColon="SameLine" BeforeIndexerDeclarationBracket="False" BeforeDelegateDeclarationParentheses="False" NewParentheses="False" SpacesBeforeBrackets="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
208 <TextStylePolicy FileWidth="120" EolMarker="Unix" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
209 <TextStylePolicy FileWidth="120" EolMarker="Unix" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
209 <DotNetNamingPolicy DirectoryNamespaceAssociation="PrefixedHierarchical" ResourceNamePolicy="MSBuild" />
210 <DotNetNamingPolicy DirectoryNamespaceAssociation="PrefixedHierarchical" ResourceNamePolicy="MSBuild" />
210 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="application/xml" />
211 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="application/xml" />
211 <XmlFormattingPolicy inheritsSet="Mono" inheritsScope="application/xml" scope="application/xml" />
212 <XmlFormattingPolicy inheritsSet="Mono" inheritsScope="application/xml" scope="application/xml" />
212 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" />
213 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" />
213 <NameConventionPolicy>
214 <NameConventionPolicy>
214 <Rules>
215 <Rules>
215 <NamingRule Name="Namespaces" AffectedEntity="Namespace" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
216 <NamingRule Name="Namespaces" AffectedEntity="Namespace" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
216 <NamingRule Name="Types" AffectedEntity="Class, Struct, Enum, Delegate" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
217 <NamingRule Name="Types" AffectedEntity="Class, Struct, Enum, Delegate" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
217 <NamingRule Name="Interfaces" AffectedEntity="Interface" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
218 <NamingRule Name="Interfaces" AffectedEntity="Interface" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
218 <RequiredPrefixes>
219 <RequiredPrefixes>
219 <String>I</String>
220 <String>I</String>
220 </RequiredPrefixes>
221 </RequiredPrefixes>
221 </NamingRule>
222 </NamingRule>
222 <NamingRule Name="Attributes" AffectedEntity="CustomAttributes" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
223 <NamingRule Name="Attributes" AffectedEntity="CustomAttributes" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
223 <RequiredSuffixes>
224 <RequiredSuffixes>
224 <String>Attribute</String>
225 <String>Attribute</String>
225 </RequiredSuffixes>
226 </RequiredSuffixes>
226 </NamingRule>
227 </NamingRule>
227 <NamingRule Name="Event Arguments" AffectedEntity="CustomEventArgs" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
228 <NamingRule Name="Event Arguments" AffectedEntity="CustomEventArgs" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
228 <RequiredSuffixes>
229 <RequiredSuffixes>
229 <String>EventArgs</String>
230 <String>EventArgs</String>
230 </RequiredSuffixes>
231 </RequiredSuffixes>
231 </NamingRule>
232 </NamingRule>
232 <NamingRule Name="Exceptions" AffectedEntity="CustomExceptions" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
233 <NamingRule Name="Exceptions" AffectedEntity="CustomExceptions" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
233 <RequiredSuffixes>
234 <RequiredSuffixes>
234 <String>Exception</String>
235 <String>Exception</String>
235 </RequiredSuffixes>
236 </RequiredSuffixes>
236 </NamingRule>
237 </NamingRule>
237 <NamingRule Name="Methods" AffectedEntity="Methods" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
238 <NamingRule Name="Methods" AffectedEntity="Methods" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
238 <NamingRule Name="Static Readonly Fields" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Protected, Public" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True" />
239 <NamingRule Name="Static Readonly Fields" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Protected, Public" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True" />
239 <NamingRule Name="Fields (Non Private)" AffectedEntity="Field" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
240 <NamingRule Name="Fields (Non Private)" AffectedEntity="Field" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
240 <NamingRule Name="ReadOnly Fields (Non Private)" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False" />
241 <NamingRule Name="ReadOnly Fields (Non Private)" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False" />
241 <NamingRule Name="Fields (Private)" AffectedEntity="Field, ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
242 <NamingRule Name="Fields (Private)" AffectedEntity="Field, ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
242 <RequiredPrefixes>
243 <RequiredPrefixes>
243 <String>m_</String>
244 <String>m_</String>
244 </RequiredPrefixes>
245 </RequiredPrefixes>
245 </NamingRule>
246 </NamingRule>
246 <NamingRule Name="Static Fields (Private)" AffectedEntity="Field" VisibilityMask="Private" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True">
247 <NamingRule Name="Static Fields (Private)" AffectedEntity="Field" VisibilityMask="Private" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True">
247 <RequiredPrefixes>
248 <RequiredPrefixes>
248 <String>_</String>
249 <String>_</String>
249 </RequiredPrefixes>
250 </RequiredPrefixes>
250 </NamingRule>
251 </NamingRule>
251 <NamingRule Name="ReadOnly Fields (Private)" AffectedEntity="ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
252 <NamingRule Name="ReadOnly Fields (Private)" AffectedEntity="ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
252 <RequiredPrefixes>
253 <RequiredPrefixes>
253 <String>m_</String>
254 <String>m_</String>
254 </RequiredPrefixes>
255 </RequiredPrefixes>
255 </NamingRule>
256 </NamingRule>
256 <NamingRule Name="Constant Fields" AffectedEntity="ConstantField" VisibilityMask="VisibilityMask" NamingStyle="AllUpper" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
257 <NamingRule Name="Constant Fields" AffectedEntity="ConstantField" VisibilityMask="VisibilityMask" NamingStyle="AllUpper" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
257 <NamingRule Name="Properties" AffectedEntity="Property" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
258 <NamingRule Name="Properties" AffectedEntity="Property" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
258 <NamingRule Name="Events" AffectedEntity="Event" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
259 <NamingRule Name="Events" AffectedEntity="Event" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
259 <NamingRule Name="Enum Members" AffectedEntity="EnumMember" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
260 <NamingRule Name="Enum Members" AffectedEntity="EnumMember" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
260 <NamingRule Name="Parameters" AffectedEntity="Parameter, LocalVariable" VisibilityMask="VisibilityMask" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
261 <NamingRule Name="Parameters" AffectedEntity="Parameter, LocalVariable" VisibilityMask="VisibilityMask" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
261 <NamingRule Name="Type Parameters" AffectedEntity="TypeParameter" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
262 <NamingRule Name="Type Parameters" AffectedEntity="TypeParameter" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
262 <RequiredPrefixes>
263 <RequiredPrefixes>
263 <String>T</String>
264 <String>T</String>
264 </RequiredPrefixes>
265 </RequiredPrefixes>
265 </NamingRule>
266 </NamingRule>
266 </Rules>
267 </Rules>
267 </NameConventionPolicy>
268 </NameConventionPolicy>
268 </Policies>
269 </Policies>
269 </Properties>
270 </Properties>
270 </MonoDevelop>
271 </MonoDevelop>
271 </ProjectExtensions>
272 </ProjectExtensions>
272 <ItemGroup>
273 <ItemGroup />
273 <Folder Include="Components\" />
274 <Folder Include="Automaton\RegularExpressions\" />
275 <Folder Include="Formats\" />
276 <Folder Include="Formats\JSON\" />
277 </ItemGroup>
278 </Project> No newline at end of file
274 </Project>
@@ -1,22 +1,25
1 using System;
1 using System;
2 using Implab.Parallels;
2 using Implab.Parallels;
3
3
4 namespace Implab {
4 namespace Implab {
5 public class Promise : AbstractPromise, IDeferred {
5 public class Promise : AbstractPromise, IDeferred {
6 public static readonly Promise SUCCESS;
6 public static readonly IPromise Success;
7
7
8 static Promise() {
8 static Promise() {
9 SUCCESS = new Promise();
9 Success = new SuccessPromise();
10 SUCCESS.Resolve();
11 }
10 }
12
11
13 public void Resolve() {
12 public void Resolve() {
14 SetResult();
13 SetResult();
15 }
14 }
16
15
17 public void Reject(Exception error) {
16 public void Reject(Exception error) {
18 SetError(error);
17 SetError(error);
19 }
18 }
19
20 public static IPromise FromException(Exception exception) {
21 return new FailedPromise(exception);
22 }
20 }
23 }
21 }
24 }
22
25
@@ -1,289 +1,300
1 using System.Threading;
1 using System.Threading;
2 using System;
2 using System;
3 using Implab.Diagnostics;
3 using Implab.Diagnostics;
4 using System.Collections.Generic;
4 using System.Collections.Generic;
5 using System.Linq;
5
6
6 namespace Implab {
7 namespace Implab {
7 public static class PromiseExtensions {
8 public static class PromiseExtensions {
8 public static IPromise<T> DispatchToCurrentContext<T>(this IPromise<T> that) {
9 public static IPromise<T> DispatchToCurrentContext<T>(this IPromise<T> that) {
9 Safe.ArgumentNotNull(that, "that");
10 Safe.ArgumentNotNull(that, "that");
10 var context = SynchronizationContext.Current;
11 var context = SynchronizationContext.Current;
11 if (context == null)
12 if (context == null)
12 return that;
13 return that;
13
14
14 var p = new SyncContextPromise<T>(context);
15 var p = new SyncContextPromise<T>(context);
15 p.CancellationRequested(that.Cancel);
16 p.CancellationRequested(that.Cancel);
16
17
17 that.On(
18 that.On(
18 p.Resolve,
19 p.Resolve,
19 p.Reject,
20 p.Reject,
20 p.CancelOperation
21 p.CancelOperation
21 );
22 );
22 return p;
23 return p;
23 }
24 }
24
25
25 public static IPromise<T> DispatchToContext<T>(this IPromise<T> that, SynchronizationContext context) {
26 public static IPromise<T> DispatchToContext<T>(this IPromise<T> that, SynchronizationContext context) {
26 Safe.ArgumentNotNull(that, "that");
27 Safe.ArgumentNotNull(that, "that");
27 Safe.ArgumentNotNull(context, "context");
28 Safe.ArgumentNotNull(context, "context");
28
29
29 var p = new SyncContextPromise<T>(context);
30 var p = new SyncContextPromise<T>(context);
30 p.CancellationRequested(that.Cancel);
31 p.CancellationRequested(that.Cancel);
31
32
32 that.On(
33 that.On(
33 p.Resolve,
34 p.Resolve,
34 p.Reject,
35 p.Reject,
35 p.CancelOperation
36 p.CancelOperation
36 );
37 );
37 return p;
38 return p;
38 }
39 }
39
40
40 /// <summary>
41 /// <summary>
41 /// Ensures the dispatched.
42 /// Ensures the dispatched.
42 /// </summary>
43 /// </summary>
43 /// <returns>The dispatched.</returns>
44 /// <returns>The dispatched.</returns>
44 /// <param name="that">That.</param>
45 /// <param name="that">That.</param>
45 /// <param name="head">Head.</param>
46 /// <param name="head">Head.</param>
46 /// <param name="cleanup">Cleanup.</param>
47 /// <param name="cleanup">Cleanup.</param>
47 /// <typeparam name="TPromise">The 1st type parameter.</typeparam>
48 /// <typeparam name="TPromise">The 1st type parameter.</typeparam>
48 /// <typeparam name="T">The 2nd type parameter.</typeparam>
49 /// <typeparam name="T">The 2nd type parameter.</typeparam>
49 public static TPromise EnsureDispatched<TPromise,T>(this TPromise that, IPromise<T> head, Action<T> cleanup) where TPromise : IPromise{
50 public static TPromise EnsureDispatched<TPromise,T>(this TPromise that, IPromise<T> head, Action<T> cleanup) where TPromise : IPromise{
50 Safe.ArgumentNotNull(that, "that");
51 Safe.ArgumentNotNull(that, "that");
51 Safe.ArgumentNotNull(head, "head");
52 Safe.ArgumentNotNull(head, "head");
52
53
53 that.On(() => head.On(cleanup), PromiseEventType.Cancelled);
54 that.On(() => head.On(cleanup), PromiseEventType.Cancelled);
54
55
55 return that;
56 return that;
56 }
57 }
57
58
58 public static AsyncCallback AsyncCallback<T>(this Promise<T> that, Func<IAsyncResult,T> callback) {
59 public static AsyncCallback AsyncCallback<T>(this Promise<T> that, Func<IAsyncResult,T> callback) {
59 Safe.ArgumentNotNull(that, "that");
60 Safe.ArgumentNotNull(that, "that");
60 Safe.ArgumentNotNull(callback, "callback");
61 Safe.ArgumentNotNull(callback, "callback");
61 var op = TraceContext.Instance.CurrentOperation;
62 var op = TraceContext.Instance.CurrentOperation;
62 return ar => {
63 return ar => {
63 TraceContext.Instance.EnterLogicalOperation(op,false);
64 TraceContext.Instance.EnterLogicalOperation(op,false);
64 try {
65 try {
65 that.Resolve(callback(ar));
66 that.Resolve(callback(ar));
66 } catch (Exception err) {
67 } catch (Exception err) {
67 that.Reject(err);
68 that.Reject(err);
68 } finally {
69 } finally {
69 TraceContext.Instance.Leave();
70 TraceContext.Instance.Leave();
70 }
71 }
71 };
72 };
72 }
73 }
73
74
74 static void CancelByTimeoutCallback(object cookie) {
75 static void CancelByTimeoutCallback(object cookie) {
75 ((ICancellable)cookie).Cancel(new TimeoutException());
76 ((ICancellable)cookie).Cancel(new TimeoutException());
76 }
77 }
77
78
78 /// <summary>
79 /// <summary>
79 /// Cancells promise after the specified timeout is elapsed.
80 /// Cancells promise after the specified timeout is elapsed.
80 /// </summary>
81 /// </summary>
81 /// <param name="that">The promise to cancel on timeout.</param>
82 /// <param name="that">The promise to cancel on timeout.</param>
82 /// <param name="milliseconds">The timeout in milliseconds.</param>
83 /// <param name="milliseconds">The timeout in milliseconds.</param>
83 /// <typeparam name="TPromise">The 1st type parameter.</typeparam>
84 /// <typeparam name="TPromise">The 1st type parameter.</typeparam>
84 public static TPromise Timeout<TPromise>(this TPromise that, int milliseconds) where TPromise : IPromise {
85 public static TPromise Timeout<TPromise>(this TPromise that, int milliseconds) where TPromise : IPromise {
85 Safe.ArgumentNotNull(that, "that");
86 Safe.ArgumentNotNull(that, "that");
86 var timer = new Timer(CancelByTimeoutCallback, that, milliseconds, -1);
87 var timer = new Timer(CancelByTimeoutCallback, that, milliseconds, -1);
87 that.On(timer.Dispose, PromiseEventType.All);
88 that.On(timer.Dispose, PromiseEventType.All);
88 return that;
89 return that;
89 }
90 }
90
91
91 public static IPromise Bundle(this ICollection<IPromise> that) {
92 public static IPromise PromiseAll(this IEnumerable<IPromise> that) {
93 Safe.ArgumentNotNull(that, "that");
94 return PromiseAll(that.ToList());
95 }
96
97 public static IPromise<T[]> PromiseAll<T>(this IEnumerable<IPromise<T>> that) {
98 Safe.ArgumentNotNull(that, "that");
99 return PromiseAll(that.ToList());
100 }
101
102 public static IPromise PromiseAll(this ICollection<IPromise> that) {
92 Safe.ArgumentNotNull(that, "that");
103 Safe.ArgumentNotNull(that, "that");
93
104
94 int count = that.Count;
105 int count = that.Count;
95 int errors = 0;
106 int errors = 0;
96 var medium = new Promise();
107 var medium = new Promise();
97
108
98 if (count == 0) {
109 if (count == 0) {
99 medium.Resolve();
110 medium.Resolve();
100 return medium;
111 return medium;
101 }
112 }
102
113
103 medium.On(() => {
114 medium.On(() => {
104 foreach(var p2 in that)
115 foreach(var p2 in that)
105 p2.Cancel();
116 p2.Cancel();
106 }, PromiseEventType.ErrorOrCancel);
117 }, PromiseEventType.ErrorOrCancel);
107
118
108 foreach (var p in that)
119 foreach (var p in that)
109 p.On(
120 p.On(
110 () => {
121 () => {
111 if (Interlocked.Decrement(ref count) == 0)
122 if (Interlocked.Decrement(ref count) == 0)
112 medium.Resolve();
123 medium.Resolve();
113 },
124 },
114 error => {
125 error => {
115 if (Interlocked.Increment(ref errors) == 1)
126 if (Interlocked.Increment(ref errors) == 1)
116 medium.Reject(
127 medium.Reject(
117 new Exception("The dependency promise is failed", error)
128 new Exception("The dependency promise is failed", error)
118 );
129 );
119 },
130 },
120 reason => {
131 reason => {
121 if (Interlocked.Increment(ref errors) == 1)
132 if (Interlocked.Increment(ref errors) == 1)
122 medium.Cancel(
133 medium.Cancel(
123 new Exception("The dependency promise is cancelled")
134 new Exception("The dependency promise is cancelled")
124 );
135 );
125 }
136 }
126 );
137 );
127
138
128 return medium;
139 return medium;
129 }
140 }
130
141
131 public static IPromise<T[]> Bundle<T>(this ICollection<IPromise<T>> that) {
142 public static IPromise<T[]> PromiseAll<T>(this ICollection<IPromise<T>> that) {
132 Safe.ArgumentNotNull(that, "that");
143 Safe.ArgumentNotNull(that, "that");
133
144
134 int count = that.Count;
145 int count = that.Count;
135 int errors = 0;
146 int errors = 0;
136 var medium = new Promise<T[]>();
147 var medium = new Promise<T[]>();
137 var results = new T[that.Count];
148 var results = new T[that.Count];
138
149
139 medium.On(() => {
150 medium.On(() => {
140 foreach(var p2 in that)
151 foreach(var p2 in that)
141 p2.Cancel();
152 p2.Cancel();
142 }, PromiseEventType.ErrorOrCancel);
153 }, PromiseEventType.ErrorOrCancel);
143
154
144 int i = 0;
155 int i = 0;
145 foreach (var p in that) {
156 foreach (var p in that) {
146 var idx = i;
157 var idx = i;
147 p.On(
158 p.On(
148 x => {
159 x => {
149 results[idx] = x;
160 results[idx] = x;
150 if (Interlocked.Decrement(ref count) == 0)
161 if (Interlocked.Decrement(ref count) == 0)
151 medium.Resolve(results);
162 medium.Resolve(results);
152 },
163 },
153 error => {
164 error => {
154 if (Interlocked.Increment(ref errors) == 1)
165 if (Interlocked.Increment(ref errors) == 1)
155 medium.Reject(
166 medium.Reject(
156 new Exception("The dependency promise is failed", error)
167 new Exception("The dependency promise is failed", error)
157 );
168 );
158 },
169 },
159 reason => {
170 reason => {
160 if (Interlocked.Increment(ref errors) == 1)
171 if (Interlocked.Increment(ref errors) == 1)
161 medium.Cancel(
172 medium.Cancel(
162 new Exception("The dependency promise is cancelled", reason)
173 new Exception("The dependency promise is cancelled", reason)
163 );
174 );
164 }
175 }
165 );
176 );
166 i++;
177 i++;
167 }
178 }
168
179
169 return medium;
180 return medium;
170 }
181 }
171
182
172 public static IPromise Then(this IPromise that, Action success, Action<Exception> error, Action<Exception> cancel) {
183 public static IPromise Then(this IPromise that, Action success, Action<Exception> error, Action<Exception> cancel) {
173 Safe.ArgumentNotNull(that, "that");
184 Safe.ArgumentNotNull(that, "that");
174
185
175 var d = new ActionTask(success, error, cancel, false);
186 var d = new ActionTask(success, error, cancel, false);
176 that.On(d.Resolve, d.Reject, d.CancelOperation);
187 that.On(d.Resolve, d.Reject, d.CancelOperation);
177 d.CancellationRequested(that.Cancel);
188 d.CancellationRequested(that.Cancel);
178 return d;
189 return d;
179 }
190 }
180
191
181 public static IPromise Then(this IPromise that, Action success, Action<Exception> error) {
192 public static IPromise Then(this IPromise that, Action success, Action<Exception> error) {
182 return Then(that, success, error, null);
193 return Then(that, success, error, null);
183 }
194 }
184
195
185 public static IPromise Then(this IPromise that, Action success) {
196 public static IPromise Then(this IPromise that, Action success) {
186 return Then(that, success, null, null);
197 return Then(that, success, null, null);
187 }
198 }
188
199
189 public static IPromise<T> Then<T>(this IPromise that, Func<T> success, Func<Exception, T> error, Func<Exception, T> cancel) {
200 public static IPromise<T> Then<T>(this IPromise that, Func<T> success, Func<Exception, T> error, Func<Exception, T> cancel) {
190 Safe.ArgumentNotNull(that, "that");
201 Safe.ArgumentNotNull(that, "that");
191
202
192 var d = new FuncTask<T>(success, error, cancel, false);
203 var d = new FuncTask<T>(success, error, cancel, false);
193 that.On(d.Resolve, d.Reject, d.CancelOperation);
204 that.On(d.Resolve, d.Reject, d.CancelOperation);
194 d.CancellationRequested(that.Cancel);
205 d.CancellationRequested(that.Cancel);
195 return d;
206 return d;
196 }
207 }
197
208
198 public static IPromise<T> Then<T>(this IPromise that, Func<T> success, Func<Exception, T> error) {
209 public static IPromise<T> Then<T>(this IPromise that, Func<T> success, Func<Exception, T> error) {
199 return Then(that, success, error, null);
210 return Then(that, success, error, null);
200 }
211 }
201
212
202 public static IPromise<T> Then<T>(this IPromise that, Func<T> success) {
213 public static IPromise<T> Then<T>(this IPromise that, Func<T> success) {
203 return Then(that, success, null, null);
214 return Then(that, success, null, null);
204 }
215 }
205
216
206 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success, Func<Exception, T2> error, Func<Exception, T2> cancel) {
217 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success, Func<Exception, T2> error, Func<Exception, T2> cancel) {
207 Safe.ArgumentNotNull(that, "that");
218 Safe.ArgumentNotNull(that, "that");
208 var d = new FuncTask<T,T2>(success, error, cancel, false);
219 var d = new FuncTask<T,T2>(success, error, cancel, false);
209 that.On(d.Resolve, d.Reject, d.CancelOperation);
220 that.On(d.Resolve, d.Reject, d.CancelOperation);
210 d.CancellationRequested(that.Cancel);
221 d.CancellationRequested(that.Cancel);
211 return d;
222 return d;
212 }
223 }
213
224
214 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success, Func<Exception, T2> error) {
225 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success, Func<Exception, T2> error) {
215 return Then(that, success, error, null);
226 return Then(that, success, error, null);
216 }
227 }
217
228
218 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success) {
229 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success) {
219 return Then(that, success, null, null);
230 return Then(that, success, null, null);
220 }
231 }
221
232
222 #region chain traits
233 #region chain traits
223 public static IPromise Chain(this IPromise that, Func<IPromise> success, Func<Exception,IPromise> error, Func<Exception,IPromise> cancel) {
234 public static IPromise Chain(this IPromise that, Func<IPromise> success, Func<Exception,IPromise> error, Func<Exception,IPromise> cancel) {
224 Safe.ArgumentNotNull(that, "that");
235 Safe.ArgumentNotNull(that, "that");
225
236
226 var d = new ActionChainTask(success, error, cancel, false);
237 var d = new ActionChainTask(success, error, cancel, false);
227 that.On(d.Resolve, d.Reject, d.CancelOperation);
238 that.On(d.Resolve, d.Reject, d.CancelOperation);
228 d.CancellationRequested(that.Cancel);
239 d.CancellationRequested(that.Cancel);
229 return d;
240 return d;
230 }
241 }
231
242
232 public static IPromise Chain(this IPromise that, Func<IPromise> success, Func<Exception,IPromise> error) {
243 public static IPromise Chain(this IPromise that, Func<IPromise> success, Func<Exception,IPromise> error) {
233 return Chain(that, success, error, null);
244 return Chain(that, success, error, null);
234 }
245 }
235
246
236 public static IPromise Chain(this IPromise that, Func<IPromise> success) {
247 public static IPromise Chain(this IPromise that, Func<IPromise> success) {
237 return Chain(that, success, null, null);
248 return Chain(that, success, null, null);
238 }
249 }
239
250
240 public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success, Func<Exception, IPromise<T>> error, Func<Exception, IPromise<T>> cancel) {
251 public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success, Func<Exception, IPromise<T>> error, Func<Exception, IPromise<T>> cancel) {
241 Safe.ArgumentNotNull(that, "that");
252 Safe.ArgumentNotNull(that, "that");
242
253
243 var d = new FuncChainTask<T>(success, error, cancel, false);
254 var d = new FuncChainTask<T>(success, error, cancel, false);
244 that.On(d.Resolve, d.Reject, d.CancelOperation);
255 that.On(d.Resolve, d.Reject, d.CancelOperation);
245 if (success != null)
256 if (success != null)
246 d.CancellationRequested(that.Cancel);
257 d.CancellationRequested(that.Cancel);
247 return d;
258 return d;
248 }
259 }
249
260
250 public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success, Func<Exception, IPromise<T>> error) {
261 public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success, Func<Exception, IPromise<T>> error) {
251 return Chain(that, success, error, null);
262 return Chain(that, success, error, null);
252 }
263 }
253
264
254 public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success) {
265 public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success) {
255 return Chain(that, success, null, null);
266 return Chain(that, success, null, null);
256 }
267 }
257
268
258 public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success, Func<Exception, IPromise<T2>> error, Func<Exception, IPromise<T2>> cancel) {
269 public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success, Func<Exception, IPromise<T2>> error, Func<Exception, IPromise<T2>> cancel) {
259 Safe.ArgumentNotNull(that, "that");
270 Safe.ArgumentNotNull(that, "that");
260 var d = new FuncChainTask<T,T2>(success, error, cancel, false);
271 var d = new FuncChainTask<T,T2>(success, error, cancel, false);
261 that.On(d.Resolve, d.Reject, d.CancelOperation);
272 that.On(d.Resolve, d.Reject, d.CancelOperation);
262 if (success != null)
273 if (success != null)
263 d.CancellationRequested(that.Cancel);
274 d.CancellationRequested(that.Cancel);
264 return d;
275 return d;
265 }
276 }
266
277
267 public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success, Func<Exception, IPromise<T2>> error) {
278 public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success, Func<Exception, IPromise<T2>> error) {
268 return Chain(that, success, error, null);
279 return Chain(that, success, error, null);
269 }
280 }
270
281
271 public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success) {
282 public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success) {
272 return Chain(that, success, null, null);
283 return Chain(that, success, null, null);
273 }
284 }
274
285
275 #endregion
286 #endregion
276
287
277
288
278 #if NET_4_5
289 #if NET_4_5
279
290
280 public static PromiseAwaiter<T> GetAwaiter<T>(this IPromise<T> that) {
291 public static PromiseAwaiter<T> GetAwaiter<T>(this IPromise<T> that) {
281 Safe.ArgumentNotNull(that, "that");
292 Safe.ArgumentNotNull(that, "that");
282
293
283 return new PromiseAwaiter<T>(that);
294 return new PromiseAwaiter<T>(that);
284 }
295 }
285
296
286 #endif
297 #endif
287 }
298 }
288 }
299 }
289
300
@@ -1,114 +1,114
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
3 using System.Linq;
4 using System.Text;
4 using System.Text;
5 using System.Text.RegularExpressions;
5 using System.Text.RegularExpressions;
6 using System.Diagnostics;
6 using System.Diagnostics;
7
7
8 namespace Implab
8 namespace Implab
9 {
9 {
10 public static class Safe
10 public static class Safe
11 {
11 {
12 public static void ArgumentAssert(bool condition, string paramName) {
12 public static void ArgumentAssert(bool condition, string paramName) {
13 if (!condition)
13 if (!condition)
14 throw new ArgumentException("The parameter is invalid", paramName);
14 throw new ArgumentException("The parameter is invalid", paramName);
15 }
15 }
16
16
17 public static void ArgumentMatch(string value, string paramName, Regex rx) {
17 public static void ArgumentMatch(string value, string paramName, Regex rx) {
18 if (rx == null)
18 if (rx == null)
19 throw new ArgumentNullException("rx");
19 throw new ArgumentNullException("rx");
20 if (!rx.IsMatch(value))
20 if (!rx.IsMatch(value))
21 throw new ArgumentException(String.Format("The prameter value must match {0}", rx), paramName);
21 throw new ArgumentException(String.Format("The prameter value must match {0}", rx), paramName);
22 }
22 }
23
23
24 public static void ArgumentNotEmpty(string value, string paramName) {
24 public static void ArgumentNotEmpty(string value, string paramName) {
25 if (String.IsNullOrEmpty(value))
25 if (String.IsNullOrEmpty(value))
26 throw new ArgumentException("The parameter can't be empty", paramName);
26 throw new ArgumentException("The parameter can't be empty", paramName);
27 }
27 }
28
28
29 public static void ArgumentNotEmpty<T>(T[] value, string paramName) {
29 public static void ArgumentNotEmpty<T>(T[] value, string paramName) {
30 if (value == null || value.Length == 0)
30 if (value == null || value.Length == 0)
31 throw new ArgumentException("The array must be not emty", paramName);
31 throw new ArgumentException("The array must be not emty", paramName);
32 }
32 }
33
33
34 public static void ArgumentNotNull(object value, string paramName) {
34 public static void ArgumentNotNull(object value, string paramName) {
35 if (value == null)
35 if (value == null)
36 throw new ArgumentNullException(paramName);
36 throw new ArgumentNullException(paramName);
37 }
37 }
38
38
39 public static void ArgumentInRange(int value, int min, int max, string paramName) {
39 public static void ArgumentInRange(int value, int min, int max, string paramName) {
40 if (value < min || value > max)
40 if (value < min || value > max)
41 throw new ArgumentOutOfRangeException(paramName);
41 throw new ArgumentOutOfRangeException(paramName);
42 }
42 }
43
43
44 public static void ArgumentOfType(object value, Type type, string paramName) {
44 public static void ArgumentOfType(object value, Type type, string paramName) {
45 if (!type.IsInstanceOfType(value))
45 if (!type.IsInstanceOfType(value))
46 throw new ArgumentException(String.Format("The parameter must be of type {0}", type), paramName);
46 throw new ArgumentException(String.Format("The parameter must be of type {0}", type), paramName);
47 }
47 }
48
48
49 public static void Dispose(params IDisposable[] objects) {
49 public static void Dispose(params IDisposable[] objects) {
50 foreach (var d in objects)
50 foreach (var d in objects)
51 if (d != null)
51 if (d != null)
52 d.Dispose();
52 d.Dispose();
53 }
53 }
54
54
55 public static void Dispose(params object[] objects) {
55 public static void Dispose(params object[] objects) {
56 foreach (var obj in objects) {
56 foreach (var obj in objects) {
57 var d = obj as IDisposable;
57 var d = obj as IDisposable;
58 if (d != null)
58 if (d != null)
59 d.Dispose();
59 d.Dispose();
60 }
60 }
61 }
61 }
62
62
63 public static void Dispose(object obj) {
63 public static void Dispose(object obj) {
64 var d = obj as IDisposable;
64 var d = obj as IDisposable;
65 if (d != null)
65 if (d != null)
66 d.Dispose();
66 d.Dispose();
67 }
67 }
68
68
69 [DebuggerStepThrough]
69 [DebuggerStepThrough]
70 public static IPromise<T> Run<T>(Func<T> action) {
70 public static IPromise<T> Run<T>(Func<T> action) {
71 ArgumentNotNull(action, "action");
71 ArgumentNotNull(action, "action");
72
72
73 try {
73 try {
74 return Promise<T>.FromResult(action());
74 return Promise<T>.FromResult(action());
75 } catch (Exception err) {
75 } catch (Exception err) {
76 return Promise<T>.FromException(err);
76 return Promise<T>.FromException(err);
77 }
77 }
78 }
78 }
79
79
80 [DebuggerStepThrough]
80 [DebuggerStepThrough]
81 public static IPromise Run(Action action) {
81 public static IPromise Run(Action action) {
82 ArgumentNotNull(action, "action");
82 ArgumentNotNull(action, "action");
83
83
84 try {
84 try {
85 action();
85 action();
86 return Promise.SUCCESS;
86 return Promise.Success;
87 } catch (Exception err) {
87 } catch (Exception err) {
88 return new FailedPromise(err);
88 return new FailedPromise(err);
89 }
89 }
90 }
90 }
91
91
92 [DebuggerStepThrough]
92 [DebuggerStepThrough]
93 public static IPromise Run(Func<IPromise> action) {
93 public static IPromise Run(Func<IPromise> action) {
94 ArgumentNotNull(action, "action");
94 ArgumentNotNull(action, "action");
95
95
96 try {
96 try {
97 return action() ?? new FailedPromise(new Exception("The action returned null"));
97 return action() ?? new FailedPromise(new Exception("The action returned null"));
98 } catch (Exception err) {
98 } catch (Exception err) {
99 return new FailedPromise(err);
99 return new FailedPromise(err);
100 }
100 }
101 }
101 }
102
102
103 [DebuggerStepThrough]
103 [DebuggerStepThrough]
104 public static IPromise<T> Run<T>(Func<IPromise<T>> action) {
104 public static IPromise<T> Run<T>(Func<IPromise<T>> action) {
105 ArgumentNotNull(action, "action");
105 ArgumentNotNull(action, "action");
106
106
107 try {
107 try {
108 return action() ?? Promise<T>.FromException(new Exception("The action returned null"));
108 return action() ?? Promise<T>.FromException(new Exception("The action returned null"));
109 } catch (Exception err) {
109 } catch (Exception err) {
110 return Promise<T>.FromException(err);
110 return Promise<T>.FromException(err);
111 }
111 }
112 }
112 }
113 }
113 }
114 }
114 }
General Comments 3
Under Review
author

Auto status change to "Under Review"

Approved
author

ok, latest stable version should be in default

You need to be logged in to leave comments. Login now