##// END OF EJS Templates
minor fixes
cin -
r105:4d308952fd5e v2
parent child
Show More
@@ -1,434 +1,449
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 TestMethod = NUnit.Framework.TestAttribute;
10 using TestMethod = 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.Cancel();
54 p.Cancel();
55
55
56 var p2 = p.Cancelled(() => {
56 var p2 = p.Cancelled(() => {
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.Cancel();
72 p.Cancel();
73
73
74 var p2 = p
74 var p2 = p
75 .Cancelled(() => {
75 .Cancelled(() => {
76 throw new ApplicationException("CANCELLED");
76 throw new ApplicationException("CANCELLED");
77 })
77 })
78 .Error(e => true);
78 .Error(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.Error(e => 101);
119 var p2 = p.Error(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() {
143 var p1 = new Promise<int>();
144
145 var p3 = p1.Chain(x => {
146 var p2 = new Promise<string>();
147 p2.Reject(new Exception("DIE!!!"));
148 return p2;
149 });
150
151 p1.Resolve(100);
152
153 Assert.IsTrue(p3.IsResolved);
154 }
155
156 [TestMethod]
142 public void PoolTest() {
157 public void PoolTest() {
143 var pid = Thread.CurrentThread.ManagedThreadId;
158 var pid = Thread.CurrentThread.ManagedThreadId;
144 var p = AsyncPool.Invoke(() => Thread.CurrentThread.ManagedThreadId);
159 var p = AsyncPool.Invoke(() => Thread.CurrentThread.ManagedThreadId);
145
160
146 Assert.AreNotEqual(pid, p.Join());
161 Assert.AreNotEqual(pid, p.Join());
147 }
162 }
148
163
149 [TestMethod]
164 [TestMethod]
150 public void WorkerPoolSizeTest() {
165 public void WorkerPoolSizeTest() {
151 var pool = new WorkerPool(5, 10, 1);
166 var pool = new WorkerPool(5, 10, 1);
152
167
153 Assert.AreEqual(5, pool.PoolSize);
168 Assert.AreEqual(5, pool.PoolSize);
154
169
155 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
170 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
156 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
171 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
157 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
172 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
158
173
159 Assert.AreEqual(5, pool.PoolSize);
174 Assert.AreEqual(5, pool.PoolSize);
160
175
161 for (int i = 0; i < 100; i++)
176 for (int i = 0; i < 100; i++)
162 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
177 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
163 Thread.Sleep(200);
178 Thread.Sleep(200);
164 Assert.AreEqual(10, pool.PoolSize);
179 Assert.AreEqual(10, pool.PoolSize);
165
180
166 pool.Dispose();
181 pool.Dispose();
167 }
182 }
168
183
169 [TestMethod]
184 [TestMethod]
170 public void WorkerPoolCorrectTest() {
185 public void WorkerPoolCorrectTest() {
171 var pool = new WorkerPool(0,1000,100);
186 var pool = new WorkerPool(0,1000,100);
172
187
173 const int iterations = 1000;
188 const int iterations = 1000;
174 int pending = iterations;
189 int pending = iterations;
175 var stop = new ManualResetEvent(false);
190 var stop = new ManualResetEvent(false);
176
191
177 var count = 0;
192 var count = 0;
178 for (int i = 0; i < iterations; i++) {
193 for (int i = 0; i < iterations; i++) {
179 pool
194 pool
180 .Invoke(() => 1)
195 .Invoke(() => 1)
181 .Then(x => Interlocked.Add(ref count, x))
196 .Then(x => Interlocked.Add(ref count, x))
182 .Then(x => Math.Log10(x))
197 .Then(x => Math.Log10(x))
183 .Anyway(() => {
198 .Anyway(() => {
184 Interlocked.Decrement(ref pending);
199 Interlocked.Decrement(ref pending);
185 if (pending == 0)
200 if (pending == 0)
186 stop.Set();
201 stop.Set();
187 });
202 });
188 }
203 }
189
204
190 stop.WaitOne();
205 stop.WaitOne();
191
206
192 Assert.AreEqual(iterations, count);
207 Assert.AreEqual(iterations, count);
193 Console.WriteLine("Max threads: {0}", pool.MaxRunningThreads);
208 Console.WriteLine("Max threads: {0}", pool.MaxRunningThreads);
194 pool.Dispose();
209 pool.Dispose();
195
210
196 }
211 }
197
212
198 [TestMethod]
213 [TestMethod]
199 public void WorkerPoolDisposeTest() {
214 public void WorkerPoolDisposeTest() {
200 var pool = new WorkerPool(5, 20);
215 var pool = new WorkerPool(5, 20);
201 Assert.AreEqual(5, pool.PoolSize);
216 Assert.AreEqual(5, pool.PoolSize);
202 pool.Dispose();
217 pool.Dispose();
203 Thread.Sleep(500);
218 Thread.Sleep(500);
204 Assert.AreEqual(0, pool.PoolSize);
219 Assert.AreEqual(0, pool.PoolSize);
205 pool.Dispose();
220 pool.Dispose();
206 }
221 }
207
222
208 [TestMethod]
223 [TestMethod]
209 public void MTQueueTest() {
224 public void MTQueueTest() {
210 var queue = new MTQueue<int>();
225 var queue = new MTQueue<int>();
211 int res;
226 int res;
212
227
213 queue.Enqueue(10);
228 queue.Enqueue(10);
214 Assert.IsTrue(queue.TryDequeue(out res));
229 Assert.IsTrue(queue.TryDequeue(out res));
215 Assert.AreEqual(10, res);
230 Assert.AreEqual(10, res);
216 Assert.IsFalse(queue.TryDequeue(out res));
231 Assert.IsFalse(queue.TryDequeue(out res));
217
232
218 for (int i = 0; i < 1000; i++)
233 for (int i = 0; i < 1000; i++)
219 queue.Enqueue(i);
234 queue.Enqueue(i);
220
235
221 for (int i = 0; i < 1000; i++) {
236 for (int i = 0; i < 1000; i++) {
222 queue.TryDequeue(out res);
237 queue.TryDequeue(out res);
223 Assert.AreEqual(i, res);
238 Assert.AreEqual(i, res);
224 }
239 }
225
240
226 int writers = 0;
241 int writers = 0;
227 int readers = 0;
242 int readers = 0;
228 var stop = new ManualResetEvent(false);
243 var stop = new ManualResetEvent(false);
229 int total = 0;
244 int total = 0;
230
245
231 const int itemsPerWriter = 10000;
246 const int itemsPerWriter = 10000;
232 const int writersCount = 10;
247 const int writersCount = 10;
233
248
234 for (int i = 0; i < writersCount; i++) {
249 for (int i = 0; i < writersCount; i++) {
235 Interlocked.Increment(ref writers);
250 Interlocked.Increment(ref writers);
236 AsyncPool
251 AsyncPool
237 .InvokeNewThread(() => {
252 .InvokeNewThread(() => {
238 for (int ii = 0; ii < itemsPerWriter; ii++) {
253 for (int ii = 0; ii < itemsPerWriter; ii++) {
239 queue.Enqueue(1);
254 queue.Enqueue(1);
240 }
255 }
241 return 1;
256 return 1;
242 })
257 })
243 .Anyway(() => Interlocked.Decrement(ref writers));
258 .Anyway(() => Interlocked.Decrement(ref writers));
244 }
259 }
245
260
246 for (int i = 0; i < 10; i++) {
261 for (int i = 0; i < 10; i++) {
247 Interlocked.Increment(ref readers);
262 Interlocked.Increment(ref readers);
248 AsyncPool
263 AsyncPool
249 .InvokeNewThread(() => {
264 .InvokeNewThread(() => {
250 int t;
265 int t;
251 do {
266 do {
252 while (queue.TryDequeue(out t))
267 while (queue.TryDequeue(out t))
253 Interlocked.Add(ref total, t);
268 Interlocked.Add(ref total, t);
254 } while (writers > 0);
269 } while (writers > 0);
255 return 1;
270 return 1;
256 })
271 })
257 .Anyway(() => {
272 .Anyway(() => {
258 Interlocked.Decrement(ref readers);
273 Interlocked.Decrement(ref readers);
259 if (readers == 0)
274 if (readers == 0)
260 stop.Set();
275 stop.Set();
261 });
276 });
262 }
277 }
263
278
264 stop.WaitOne();
279 stop.WaitOne();
265
280
266 Assert.AreEqual(itemsPerWriter * writersCount, total);
281 Assert.AreEqual(itemsPerWriter * writersCount, total);
267 }
282 }
268
283
269 [TestMethod]
284 [TestMethod]
270 public void ParallelMapTest() {
285 public void ParallelMapTest() {
271
286
272 const int count = 100000;
287 const int count = 100000;
273
288
274 var args = new double[count];
289 var args = new double[count];
275 var rand = new Random();
290 var rand = new Random();
276
291
277 for (int i = 0; i < count; i++)
292 for (int i = 0; i < count; i++)
278 args[i] = rand.NextDouble();
293 args[i] = rand.NextDouble();
279
294
280 var t = Environment.TickCount;
295 var t = Environment.TickCount;
281 var res = args.ParallelMap(x => Math.Sin(x*x), 4).Join();
296 var res = args.ParallelMap(x => Math.Sin(x*x), 4).Join();
282
297
283 Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t);
298 Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t);
284
299
285 t = Environment.TickCount;
300 t = Environment.TickCount;
286 for (int i = 0; i < count; i++)
301 for (int i = 0; i < count; i++)
287 Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]);
302 Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]);
288 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
303 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
289 }
304 }
290
305
291 [TestMethod]
306 [TestMethod]
292 public void ChainedMapTest() {
307 public void ChainedMapTest() {
293
308
294 using (var pool = new WorkerPool(0,10,1)) {
309 using (var pool = new WorkerPool(0,10,1)) {
295 const int count = 10000;
310 const int count = 10000;
296
311
297 var args = new double[count];
312 var args = new double[count];
298 var rand = new Random();
313 var rand = new Random();
299
314
300 for (int i = 0; i < count; i++)
315 for (int i = 0; i < count; i++)
301 args[i] = rand.NextDouble();
316 args[i] = rand.NextDouble();
302
317
303 var t = Environment.TickCount;
318 var t = Environment.TickCount;
304 var res = args
319 var res = args
305 .ChainedMap(
320 .ChainedMap(
306 // Analysis disable once AccessToDisposedClosure
321 // Analysis disable once AccessToDisposedClosure
307 x => pool.Invoke(
322 x => pool.Invoke(
308 () => Math.Sin(x * x)
323 () => Math.Sin(x * x)
309 ),
324 ),
310 4
325 4
311 )
326 )
312 .Join();
327 .Join();
313
328
314 Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t);
329 Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t);
315
330
316 t = Environment.TickCount;
331 t = Environment.TickCount;
317 for (int i = 0; i < count; i++)
332 for (int i = 0; i < count; i++)
318 Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]);
333 Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]);
319 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
334 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
320 Console.WriteLine("Max workers: {0}", pool.MaxRunningThreads);
335 Console.WriteLine("Max workers: {0}", pool.MaxRunningThreads);
321 }
336 }
322 }
337 }
323
338
324 [TestMethod]
339 [TestMethod]
325 public void ParallelForEachTest() {
340 public void ParallelForEachTest() {
326
341
327 const int count = 100000;
342 const int count = 100000;
328
343
329 var args = new int[count];
344 var args = new int[count];
330 var rand = new Random();
345 var rand = new Random();
331
346
332 for (int i = 0; i < count; i++)
347 for (int i = 0; i < count; i++)
333 args[i] = (int)(rand.NextDouble() * 100);
348 args[i] = (int)(rand.NextDouble() * 100);
334
349
335 int result = 0;
350 int result = 0;
336
351
337 var t = Environment.TickCount;
352 var t = Environment.TickCount;
338 args.ParallelForEach(x => Interlocked.Add(ref result, x), 4).Join();
353 args.ParallelForEach(x => Interlocked.Add(ref result, x), 4).Join();
339
354
340 Console.WriteLine("Iteration complete in {0} ms, result: {1}", Environment.TickCount - t, result);
355 Console.WriteLine("Iteration complete in {0} ms, result: {1}", Environment.TickCount - t, result);
341
356
342 int result2 = 0;
357 int result2 = 0;
343
358
344 t = Environment.TickCount;
359 t = Environment.TickCount;
345 for (int i = 0; i < count; i++)
360 for (int i = 0; i < count; i++)
346 result2 += args[i];
361 result2 += args[i];
347 Assert.AreEqual(result2, result);
362 Assert.AreEqual(result2, result);
348 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
363 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
349 }
364 }
350
365
351 [TestMethod]
366 [TestMethod]
352 public void ComplexCase1Test() {
367 public void ComplexCase1Test() {
353 var flags = new bool[3];
368 var flags = new bool[3];
354
369
355 // op1 (aync 200ms) => op2 (async 200ms) => op3 (sync map)
370 // op1 (aync 200ms) => op2 (async 200ms) => op3 (sync map)
356
371
357 var step1 = PromiseHelper
372 var step1 = PromiseHelper
358 .Sleep(200, "Alan")
373 .Sleep(200, "Alan")
359 .Cancelled(() => flags[0] = true);
374 .Cancelled(() => flags[0] = true);
360 var p = step1
375 var p = step1
361 .Chain(x =>
376 .Chain(x =>
362 PromiseHelper
377 PromiseHelper
363 .Sleep(200, "Hi, " + x)
378 .Sleep(200, "Hi, " + x)
364 .Then(y => y)
379 .Then(y => y)
365 .Cancelled(() => flags[1] = true)
380 .Cancelled(() => flags[1] = true)
366 )
381 )
367 .Cancelled(() => flags[2] = true);
382 .Cancelled(() => flags[2] = true);
368 step1.Join();
383 step1.Join();
369 p.Cancel();
384 p.Cancel();
370 try {
385 try {
371 Assert.AreEqual(p.Join(), "Hi, Alan");
386 Assert.AreEqual(p.Join(), "Hi, Alan");
372 Assert.Fail("Shouldn't get here");
387 Assert.Fail("Shouldn't get here");
373 } catch (OperationCanceledException) {
388 } catch (OperationCanceledException) {
374 }
389 }
375
390
376 Assert.IsFalse(flags[0]);
391 Assert.IsFalse(flags[0]);
377 Assert.IsTrue(flags[1]);
392 Assert.IsTrue(flags[1]);
378 Assert.IsTrue(flags[2]);
393 Assert.IsTrue(flags[2]);
379 }
394 }
380
395
381 [TestMethod]
396 [TestMethod]
382 public void ChainedCancel1Test() {
397 public void ChainedCancel1Test() {
383 // ΠΏΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ сцСплСнной асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ всС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ
398 // ΠΏΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ сцСплСнной асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ всС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ
384 // Π·Π°Π²Π΅Ρ€ΡˆΠ°Ρ‚ΡŒΡΡ ошибкой OperationCanceledException
399 // Π·Π°Π²Π΅Ρ€ΡˆΠ°Ρ‚ΡŒΡΡ ошибкой OperationCanceledException
385 var p = PromiseHelper
400 var p = PromiseHelper
386 .Sleep(1, "Hi, HAL!")
401 .Sleep(1, "Hi, HAL!")
387 .Then(x => {
402 .Then(x => {
388 // запускаСм Π΄Π²Π΅ асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ
403 // запускаСм Π΄Π²Π΅ асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ
389 var result = PromiseHelper.Sleep(1000, "HEM ENABLED!!!");
404 var result = PromiseHelper.Sleep(1000, "HEM ENABLED!!!");
390 // вторая опСрация отмСняСт ΠΏΠ΅Ρ€Π²ΡƒΡŽ Π΄ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ
405 // вторая опСрация отмСняСт ΠΏΠ΅Ρ€Π²ΡƒΡŽ Π΄ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ
391 PromiseHelper
406 PromiseHelper
392 .Sleep(100, "HAL, STOP!")
407 .Sleep(100, "HAL, STOP!")
393 .Then(result.Cancel);
408 .Then(result.Cancel);
394 return result;
409 return result;
395 });
410 });
396 try {
411 try {
397 p.Join();
412 p.Join();
398 } catch (TargetInvocationException err) {
413 } catch (TargetInvocationException err) {
399 Assert.IsTrue(err.InnerException is OperationCanceledException);
414 Assert.IsTrue(err.InnerException is OperationCanceledException);
400 }
415 }
401 }
416 }
402
417
403 [TestMethod]
418 [TestMethod]
404 public void ChainedCancel2Test() {
419 public void ChainedCancel2Test() {
405 // ΠΏΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ, Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Ρ‚Π°ΠΊΠΆΠ΅ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΎΡ‚ΠΌΠ΅Π½ΡΡ‚ΡŒΡΡ
420 // ΠΏΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ, Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Ρ‚Π°ΠΊΠΆΠ΅ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΎΡ‚ΠΌΠ΅Π½ΡΡ‚ΡŒΡΡ
406 var pSurvive = new Promise<bool>();
421 var pSurvive = new Promise<bool>();
407 var hemStarted = new ManualResetEvent(false);
422 var hemStarted = new ManualResetEvent(false);
408 var p = PromiseHelper
423 var p = PromiseHelper
409 .Sleep(1, "Hi, HAL!")
424 .Sleep(1, "Hi, HAL!")
410 .Chain(x => {
425 .Chain(x => {
411 hemStarted.Set();
426 hemStarted.Set();
412 // запускаСм Π΄Π²Π΅ асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ
427 // запускаСм Π΄Π²Π΅ асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ
413 var result = PromiseHelper
428 var result = PromiseHelper
414 .Sleep(10000, "HEM ENABLED!!!")
429 .Sleep(10000, "HEM ENABLED!!!")
415 .Then(s => pSurvive.Resolve(false));
430 .Then(s => pSurvive.Resolve(false));
416
431
417 result
432 result
418 .Cancelled(() => pSurvive.Resolve(true));
433 .Cancelled(() => pSurvive.Resolve(true));
419
434
420 return result;
435 return result;
421 });
436 });
422
437
423 hemStarted.WaitOne();
438 hemStarted.WaitOne();
424 p.Cancel();
439 p.Cancel();
425
440
426 try {
441 try {
427 p.Join();
442 p.Join();
428 } catch (OperationCanceledException) {
443 } catch (OperationCanceledException) {
429 Assert.IsTrue(pSurvive.Join());
444 Assert.IsTrue(pSurvive.Join());
430 }
445 }
431 }
446 }
432 }
447 }
433 }
448 }
434
449
@@ -1,932 +1,932
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Reflection;
3 using System.Reflection;
4 using System.Threading;
4 using System.Threading;
5 using Implab.Parallels;
5 using Implab.Parallels;
6
6
7 namespace Implab {
7 namespace Implab {
8
8
9 /// <summary>
9 /// <summary>
10 /// Класс для асинхронного получСния Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ². Π’Π°ΠΊ Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΠΎΠ΅ "ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅".
10 /// Класс для асинхронного получСния Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ². Π’Π°ΠΊ Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΠΎΠ΅ "ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅".
11 /// </summary>
11 /// </summary>
12 /// <typeparam name="T">Π’ΠΈΠΏ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌΠΎΠ³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°</typeparam>
12 /// <typeparam name="T">Π’ΠΈΠΏ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌΠΎΠ³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°</typeparam>
13 /// <remarks>
13 /// <remarks>
14 /// <para>БСрвис ΠΏΡ€ΠΈ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ ΠΊ Π΅Π³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρƒ Π΄Π°Π΅Ρ‚ ΠΎΠ±Π΅Ρ‰Π°ΠΈΠ½ΠΈΠ΅ ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ,
14 /// <para>БСрвис ΠΏΡ€ΠΈ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ ΠΊ Π΅Π³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρƒ Π΄Π°Π΅Ρ‚ ΠΎΠ±Π΅Ρ‰Π°ΠΈΠ½ΠΈΠ΅ ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ,
15 /// ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ² Ρ‚Π°ΠΊΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ряд ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹Ρ… Π²Ρ‹Π·ΠΎΠ²ΠΎ для получСния
15 /// ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ² Ρ‚Π°ΠΊΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ряд ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹Ρ… Π²Ρ‹Π·ΠΎΠ²ΠΎ для получСния
16 /// событий выполнСния обСщания, Ρ‚ΠΎΠ΅ΡΡ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΈ прСдоставлСнии Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ².</para>
16 /// событий выполнСния обСщания, Ρ‚ΠΎΠ΅ΡΡ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΈ прСдоставлСнии Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ².</para>
17 /// <para>
17 /// <para>
18 /// ΠžΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚Π°ΠΊ ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ с ошибкой. Для подписки Π½Π°
18 /// ΠžΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚Π°ΠΊ ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ с ошибкой. Для подписки Π½Π°
19 /// Π΄Π°Π½Π½Ρ‹Π΅ события ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Then</c>.
19 /// Π΄Π°Π½Π½Ρ‹Π΅ события ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Then</c>.
20 /// </para>
20 /// </para>
21 /// <para>
21 /// <para>
22 /// БСрвис, Π² свою ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ, ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ (Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ с ошибкой),
22 /// БСрвис, Π² свою ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ, ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ (Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ с ошибкой),
23 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Resolve</c> Π»ΠΈΠ±ΠΎ <c>Reject</c> для оповСщСния ΠΊΠ»ΠΈΠ΅Ρ‚Π½Π° ΠΎ
23 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Resolve</c> Π»ΠΈΠ±ΠΎ <c>Reject</c> для оповСщСния ΠΊΠ»ΠΈΠ΅Ρ‚Π½Π° ΠΎ
24 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ обСщания.
24 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ обСщания.
25 /// </para>
25 /// </para>
26 /// <para>
26 /// <para>
27 /// Если сСрвСр успСл Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΅Ρ‰Π΅ Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π½Π° Π½Π΅Π³ΠΎ подписался,
27 /// Если сСрвСр успСл Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΅Ρ‰Π΅ Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π½Π° Π½Π΅Π³ΠΎ подписался,
28 /// Ρ‚ΠΎ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ подписки ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΠ²ΡƒΡŽΡ‰ΠΈΠ΅ события Π² синхронном
28 /// Ρ‚ΠΎ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ подписки ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΠ²ΡƒΡŽΡ‰ΠΈΠ΅ события Π² синхронном
29 /// Ρ€Π΅ΠΆΠΈΠΌΠ΅ ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΠΎΠ²Π΅Ρ‰Π΅Π½ Π² любом случаС. Π˜Π½Π°Ρ‡Π΅, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ΡΡ Π²
29 /// Ρ€Π΅ΠΆΠΈΠΌΠ΅ ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΠΎΠ²Π΅Ρ‰Π΅Π½ Π² любом случаС. Π˜Π½Π°Ρ‡Π΅, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ΡΡ Π²
30 /// список Π² порядкС подписания ΠΈ Π² этом ΠΆΠ΅ порядкС ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ
30 /// список Π² порядкС подписания ΠΈ Π² этом ΠΆΠ΅ порядкС ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ
31 /// обСщания.
31 /// обСщания.
32 /// </para>
32 /// </para>
33 /// <para>
33 /// <para>
34 /// ΠžΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ обСщания ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Π»ΠΈΠ±ΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ
34 /// ΠžΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ обСщания ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Π»ΠΈΠ±ΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ
35 /// связанныС асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ‚Π°ΠΊΠΆΠ΅ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ обСщания. Для этого слСдуСт
35 /// связанныС асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ‚Π°ΠΊΠΆΠ΅ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ обСщания. Для этого слСдуСт
36 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ Ρ„ΠΎΡ€ΠΌΡƒ ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ <c>Then</c>.
36 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ Ρ„ΠΎΡ€ΠΌΡƒ ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ <c>Then</c>.
37 /// </para>
37 /// </para>
38 /// <para>
38 /// <para>
39 /// Π’Π°ΠΊΠΆΠ΅ Ρ…ΠΎΡ€ΠΎΡˆΠΈΠΌ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎΠΌ являСтся Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ <c>Resolve</c> ΠΈ <c>Reject</c> Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ
39 /// Π’Π°ΠΊΠΆΠ΅ Ρ…ΠΎΡ€ΠΎΡˆΠΈΠΌ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎΠΌ являСтся Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ <c>Resolve</c> ΠΈ <c>Reject</c> Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ
40 /// Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€ обСщания ΠΈΠ½Π°Ρ‡Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ΡŒ противорСчия.
40 /// Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€ обСщания ΠΈΠ½Π°Ρ‡Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ΡŒ противорСчия.
41 /// </para>
41 /// </para>
42 /// </remarks>
42 /// </remarks>
43 public class Promise<T> : IPromise<T> {
43 public class Promise<T> : IPromise<T> {
44
44
45 protected struct HandlerDescriptor {
45 protected struct HandlerDescriptor {
46 public Action<T> resultHandler;
46 public Action<T> resultHandler;
47 public Func<Exception,T> errorHandler;
47 public Func<Exception,T> errorHandler;
48 public Action cancellHandler;
48 public Action cancellHandler;
49 public Promise<T> medium;
49 public Promise<T> medium;
50
50
51 public void Resolve(T result) {
51 public void Resolve(T result) {
52 if (resultHandler != null) {
52 if (resultHandler != null) {
53 try {
53 try {
54 resultHandler(result);
54 resultHandler(result);
55 } catch (Exception e) {
55 } catch (Exception e) {
56 Reject(e);
56 Reject(e);
57 return;
57 return;
58 }
58 }
59 }
59 }
60 if (medium != null)
60 if (medium != null)
61 medium.Resolve(result);
61 medium.Resolve(result);
62 }
62 }
63
63
64 public void Reject(Exception err) {
64 public void Reject(Exception err) {
65 if (errorHandler != null) {
65 if (errorHandler != null) {
66 try {
66 try {
67 var res = errorHandler(err);
67 var res = errorHandler(err);
68 if (medium != null)
68 if (medium != null)
69 medium.Resolve(res);
69 medium.Resolve(res);
70 /*} catch (TransientPromiseException err2) {
70 /*} catch (TransientPromiseException err2) {
71 if (medium != null)
71 if (medium != null)
72 medium.Reject(err2.InnerException);*/
72 medium.Reject(err2.InnerException);*/
73 } catch (Exception err2) {
73 } catch (Exception err2) {
74 if (medium != null)
74 if (medium != null)
75 medium.Reject(err2);
75 medium.Reject(err2);
76 }
76 }
77 } else if (medium != null)
77 } else if (medium != null)
78 medium.Reject(err);
78 medium.Reject(err);
79 }
79 }
80
80
81 public void Cancel() {
81 public void Cancel() {
82 if (cancellHandler != null) {
82 if (cancellHandler != null) {
83 try {
83 try {
84 cancellHandler();
84 cancellHandler();
85 } catch (Exception err) {
85 } catch (Exception err) {
86 Reject(err);
86 Reject(err);
87 return;
87 return;
88 }
88 }
89 }
89 }
90 if (medium != null)
90 if (medium != null)
91 medium.Cancel();
91 medium.Cancel();
92 }
92 }
93 }
93 }
94
94
95 const int UNRESOLVED_SATE = 0;
95 const int UNRESOLVED_SATE = 0;
96 const int TRANSITIONAL_STATE = 1;
96 const int TRANSITIONAL_STATE = 1;
97 const int SUCCEEDED_STATE = 2;
97 const int SUCCEEDED_STATE = 2;
98 const int REJECTED_STATE = 3;
98 const int REJECTED_STATE = 3;
99 const int CANCELLED_STATE = 4;
99 const int CANCELLED_STATE = 4;
100
100
101 int m_childrenCount;
101 int m_childrenCount;
102 int m_state;
102 int m_state;
103 T m_result;
103 T m_result;
104 Exception m_error;
104 Exception m_error;
105
105
106 readonly MTQueue<HandlerDescriptor> m_handlers = new MTQueue<HandlerDescriptor>();
106 readonly MTQueue<HandlerDescriptor> m_handlers = new MTQueue<HandlerDescriptor>();
107
107
108 public Promise() {
108 public Promise() {
109 }
109 }
110
110
111 public Promise(IPromise parent) {
111 public Promise(IPromise parent) {
112 if (parent != null)
112 if (parent != null)
113 AddHandler(
113 AddHandler(
114 null,
114 null,
115 null,
115 null,
116 () => {
116 () => {
117 if (parent.IsExclusive)
117 if (parent.IsExclusive)
118 parent.Cancel();
118 parent.Cancel();
119 },
119 },
120 null,
120 null,
121 false
121 false
122 );
122 );
123 }
123 }
124
124
125 bool BeginTransit() {
125 bool BeginTransit() {
126 return UNRESOLVED_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, UNRESOLVED_SATE);
126 return UNRESOLVED_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, UNRESOLVED_SATE);
127 }
127 }
128
128
129 void CompleteTransit(int state) {
129 void CompleteTransit(int state) {
130 if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, state, TRANSITIONAL_STATE))
130 if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, state, TRANSITIONAL_STATE))
131 throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state");
131 throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state");
132 }
132 }
133
133
134 void WaitTransition() {
134 void WaitTransition() {
135 while (m_state == TRANSITIONAL_STATE) {
135 while (m_state == TRANSITIONAL_STATE) {
136 Thread.MemoryBarrier();
136 Thread.MemoryBarrier();
137 }
137 }
138 }
138 }
139
139
140 public bool IsResolved {
140 public bool IsResolved {
141 get {
141 get {
142 Thread.MemoryBarrier();
142 Thread.MemoryBarrier();
143 return m_state > 1;
143 return m_state > 1;
144 }
144 }
145 }
145 }
146
146
147 public bool IsCancelled {
147 public bool IsCancelled {
148 get {
148 get {
149 Thread.MemoryBarrier();
149 Thread.MemoryBarrier();
150 return m_state == CANCELLED_STATE;
150 return m_state == CANCELLED_STATE;
151 }
151 }
152 }
152 }
153
153
154 public Type PromiseType {
154 public Type PromiseType {
155 get { return typeof(T); }
155 get { return typeof(T); }
156 }
156 }
157
157
158 /// <summary>
158 /// <summary>
159 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ.
159 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ.
160 /// </summary>
160 /// </summary>
161 /// <param name="result">Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния.</param>
161 /// <param name="result">Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния.</param>
162 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
162 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
163 public void Resolve(T result) {
163 public void Resolve(T result) {
164 if (BeginTransit()) {
164 if (BeginTransit()) {
165 m_result = result;
165 m_result = result;
166 CompleteTransit(SUCCEEDED_STATE);
166 CompleteTransit(SUCCEEDED_STATE);
167 OnStateChanged();
167 OnStateChanged();
168 } else {
168 } else {
169 WaitTransition();
169 WaitTransition();
170 if (m_state != CANCELLED_STATE)
170 if (m_state != CANCELLED_STATE)
171 throw new InvalidOperationException("The promise is already resolved");
171 throw new InvalidOperationException("The promise is already resolved");
172 }
172 }
173 }
173 }
174
174
175 /// <summary>
175 /// <summary>
176 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ. Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ выполнСния Π±ΡƒΠ΄Π΅Ρ‚ пустоС значСния.
176 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ. Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ выполнСния Π±ΡƒΠ΄Π΅Ρ‚ пустоС значСния.
177 /// </summary>
177 /// </summary>
178 /// <remarks>
178 /// <remarks>
179 /// Π”Π°Π½Π½Ρ‹ΠΉ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ ΡƒΠ΄ΠΎΠ±Π΅Π½ Π² случаях, ΠΊΠΎΠ³Π΄Π° интСрСсСн Ρ„Π°ΠΊΡ‚ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, Π½Π΅ΠΆΠ΅Π»ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.
179 /// Π”Π°Π½Π½Ρ‹ΠΉ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ ΡƒΠ΄ΠΎΠ±Π΅Π½ Π² случаях, ΠΊΠΎΠ³Π΄Π° интСрСсСн Ρ„Π°ΠΊΡ‚ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, Π½Π΅ΠΆΠ΅Π»ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.
180 /// </remarks>
180 /// </remarks>
181 public void Resolve() {
181 public void Resolve() {
182 Resolve(default(T));
182 Resolve(default(T));
183 }
183 }
184
184
185 /// <summary>
185 /// <summary>
186 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ошибкС
186 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ошибкС
187 /// </summary>
187 /// </summary>
188 /// <remarks>
188 /// <remarks>
189 /// ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС, ΠΏΡ€ΠΈ Π΅Π³ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ сразу нСсколько ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²
189 /// ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС, ΠΏΡ€ΠΈ Π΅Π³ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ сразу нСсколько ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²
190 /// ΠΌΠΎΠ³Ρƒ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ, ΠΏΡ€ΠΈ этом Ρ‚ΠΎΠ»ΡŒΠΊΠΎ пСрвая Π±ΡƒΠ΄Π΅Ρ‚ использована Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅
190 /// ΠΌΠΎΠ³Ρƒ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ, ΠΏΡ€ΠΈ этом Ρ‚ΠΎΠ»ΡŒΠΊΠΎ пСрвая Π±ΡƒΠ΄Π΅Ρ‚ использована Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅
191 /// Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΡ€ΠΎΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹.
191 /// Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΡ€ΠΎΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹.
192 /// </remarks>
192 /// </remarks>
193 /// <param name="error">Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ</param>
193 /// <param name="error">Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ</param>
194 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
194 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
195 public void Reject(Exception error) {
195 public void Reject(Exception error) {
196 if (BeginTransit()) {
196 if (BeginTransit()) {
197 m_error = error is TransientPromiseException ? error.InnerException : error;
197 m_error = error is TransientPromiseException ? error.InnerException : error;
198 CompleteTransit(REJECTED_STATE);
198 CompleteTransit(REJECTED_STATE);
199 OnStateChanged();
199 OnStateChanged();
200 } else {
200 } else {
201 WaitTransition();
201 WaitTransition();
202 if (m_state == SUCCEEDED_STATE)
202 if (m_state == SUCCEEDED_STATE)
203 throw new InvalidOperationException("The promise is already resolved");
203 throw new InvalidOperationException("The promise is already resolved");
204 }
204 }
205 }
205 }
206
206
207 /// <summary>
207 /// <summary>
208 /// ΠžΡ‚ΠΌΠ΅Π½ΡΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.
208 /// ΠžΡ‚ΠΌΠ΅Π½ΡΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.
209 /// </summary>
209 /// </summary>
210 /// <remarks>Для опрСдСлСния Π±Ρ‹Π»Π° Π»ΠΈ опСрация ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Π° слСдуСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ свойство <see cref="IsCancelled"/>.</remarks>
210 /// <remarks>Для опрСдСлСния Π±Ρ‹Π»Π° Π»ΠΈ опСрация ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Π° слСдуСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ свойство <see cref="IsCancelled"/>.</remarks>
211 public void Cancel() {
211 public void Cancel() {
212 if (BeginTransit()) {
212 if (BeginTransit()) {
213 CompleteTransit(CANCELLED_STATE);
213 CompleteTransit(CANCELLED_STATE);
214 OnStateChanged();
214 OnStateChanged();
215 }
215 }
216 }
216 }
217
217
218 public IPromise<T> Then(Action<T> success, Func<Exception,T> error, Action cancel) {
218 public IPromise<T> Then(Action<T> success, Func<Exception,T> error, Action cancel) {
219 if (success == null && error == null && cancel == null)
219 if (success == null && error == null && cancel == null)
220 return this;
220 return this;
221
221
222 var medium = new Promise<T>(this);
222 var medium = new Promise<T>(this);
223
223
224 AddHandler(success, error, cancel, medium, true);
224 AddHandler(success, error, cancel, medium, true);
225
225
226 return medium;
226 return medium;
227 }
227 }
228
228
229 /// <summary>
229 /// <summary>
230 /// Adds new handlers to this promise.
230 /// Adds new handlers to this promise.
231 /// </summary>
231 /// </summary>
232 /// <param name="success">The handler of the successfully completed operation.
232 /// <param name="success">The handler of the successfully completed operation.
233 /// This handler will recieve an operation result as a parameter.</param>
233 /// This handler will recieve an operation result as a parameter.</param>
234 /// <param name="error">Handles an exception that may occur during the operation and returns the value which will be used as the result of the operation.</param>
234 /// <param name="error">Handles an exception that may occur during the operation and returns the value which will be used as the result of the operation.</param>
235 /// <returns>The new promise chained to this one.</returns>
235 /// <returns>The new promise chained to this one.</returns>
236 public IPromise<T> Then(Action<T> success, Func<Exception,T> error) {
236 public IPromise<T> Then(Action<T> success, Func<Exception,T> error) {
237 if (success == null && error == null)
237 if (success == null && error == null)
238 return this;
238 return this;
239
239
240 var medium = new Promise<T>(this);
240 var medium = new Promise<T>(this);
241
241
242 AddHandler(success, error, null, medium, true);
242 AddHandler(success, error, null, medium, true);
243
243
244 return medium;
244 return medium;
245 }
245 }
246
246
247
247
248
248
249
249
250 public IPromise<T> Then(Action<T> success) {
250 public IPromise<T> Then(Action<T> success) {
251 if (success == null)
251 if (success == null)
252 return this;
252 return this;
253
253
254 var medium = new Promise<T>(this);
254 var medium = new Promise<T>(this);
255
255
256 AddHandler(success, null, null, medium, true);
256 AddHandler(success, null, null, medium, true);
257
257
258 return medium;
258 return medium;
259 }
259 }
260
260
261 /// <summary>
261 /// <summary>
262 /// ПослСдний ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
262 /// ПослСдний ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
263 /// </summary>
263 /// </summary>
264 /// <param name="success"></param>
264 /// <param name="success"></param>
265 /// <param name="error"></param>
265 /// <param name="error"></param>
266 /// <param name="cancel"></param>
266 /// <param name="cancel"></param>
267 /// <remarks>
267 /// <remarks>
268 /// <para>
268 /// <para>
269 /// Π”Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π½Π΅ создаСт связанного с Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΌ обСщания ΠΈ ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½ для окончания
269 /// Π”Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π½Π΅ создаСт связанного с Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΌ обСщания ΠΈ ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½ для окончания
270 /// фсинхронной Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ.
270 /// фсинхронной Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ.
271 /// </para>
271 /// </para>
272 /// <para>
272 /// <para>
273 /// Если Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ нСсколько Ρ€Π°Π·, Π»ΠΈΠ±ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, Ρ‚ΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ°
273 /// Если Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ нСсколько Ρ€Π°Π·, Π»ΠΈΠ±ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, Ρ‚ΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ°
274 /// Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ΄ΠΈΠ½ΠΎΡ‡Π½ΠΎΠΉ <see cref="IsExclusive"/> ΠΈ, ΠΊΠ°ΠΊ слСдствиС, Π±ΡƒΠ΄Π΅Ρ‚ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π° ΠΎΡ‚ΠΌΠ΅Π½Π°
274 /// Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ΄ΠΈΠ½ΠΎΡ‡Π½ΠΎΠΉ <see cref="IsExclusive"/> ΠΈ, ΠΊΠ°ΠΊ слСдствиС, Π±ΡƒΠ΄Π΅Ρ‚ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π° ΠΎΡ‚ΠΌΠ΅Π½Π°
275 /// всСй Ρ†Π΅ΠΏΠΈ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ снизу (с самого послСднСго обСщания).
275 /// всСй Ρ†Π΅ΠΏΠΈ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ снизу (с самого послСднСго обСщания).
276 /// </para>
276 /// </para>
277 /// </remarks>
277 /// </remarks>
278 public void On(Action<T> success, Action<Exception> error, Action cancel) {
278 public void On(Action<T> success, Action<Exception> error, Action cancel) {
279 if (success == null && error == null && cancel == null)
279 if (success == null && error == null && cancel == null)
280 return;
280 return;
281
281
282 Func<Exception,T> errorHandler = null;
282 Func<Exception,T> errorHandler = null;
283 if (error != null)
283 if (error != null)
284 errorHandler = err => {
284 errorHandler = err => {
285 error(err);
285 error(err);
286 return default(T);
286 return default(T);
287 };
287 };
288 AddHandler(success, errorHandler, cancel, null, false);
288 AddHandler(success, errorHandler, cancel, null, false);
289 }
289 }
290
290
291 public void On(Action<T> success, Action<Exception> error) {
291 public void On(Action<T> success, Action<Exception> error) {
292 On(success, error, null);
292 On(success, error, null);
293 }
293 }
294
294
295 public void On(Action<T> success) {
295 public void On(Action<T> success) {
296 On(success, null, null);
296 On(success, null, null);
297 }
297 }
298
298
299 public void On(Action handler, PromiseEventType events) {
299 public void On(Action handler, PromiseEventType events) {
300 Safe.ArgumentNotNull(handler, "handler");
300 Safe.ArgumentNotNull(handler, "handler");
301
301
302 Action<T> success = events.HasFlag(PromiseEventType.Success) ? new Action<T>(x => handler()) : null;
302 Action<T> success = events.HasFlag(PromiseEventType.Success) ? new Action<T>(x => handler()) : null;
303 Func<Exception,T> error = events.HasFlag(PromiseEventType.Error) ? new Func<Exception,T>(e => {
303 Func<Exception,T> error = events.HasFlag(PromiseEventType.Error) ? new Func<Exception,T>(e => {
304 handler();
304 handler();
305 return default(T);
305 return default(T);
306 }) : null;
306 }) : null;
307 Action cancel = events.HasFlag(PromiseEventType.Cancelled) ? handler : null;
307 Action cancel = events.HasFlag(PromiseEventType.Cancelled) ? handler : null;
308
308
309 AddHandler(success, error, cancel, null, false);
309 AddHandler(success, error, cancel, null, false);
310 }
310 }
311
311
312 public IPromise Error(Action<Exception> error) {
312 public IPromise Error(Action<Exception> error) {
313 if (error == null)
313 if (error == null)
314 return this;
314 return this;
315
315
316 var medium = new Promise<T>(this);
316 var medium = new Promise<T>(this);
317
317
318 AddHandler(
318 AddHandler(
319 null,
319 null,
320 e => {
320 e => {
321 error(e);
321 error(e);
322 return default(T);
322 return default(T);
323 },
323 },
324 null,
324 null,
325 medium,
325 medium,
326 true
326 true
327 );
327 );
328
328
329 return medium;
329 return medium;
330 }
330 }
331
331
332 /// <summary>
332 /// <summary>
333 /// Handles error and allows to keep the promise.
333 /// Handles error and allows to keep the promise.
334 /// </summary>
334 /// </summary>
335 /// <remarks>
335 /// <remarks>
336 /// If the specified handler throws an exception, this exception will be used to reject the promise.
336 /// If the specified handler throws an exception, this exception will be used to reject the promise.
337 /// </remarks>
337 /// </remarks>
338 /// <param name="handler">The error handler which returns the result of the promise.</param>
338 /// <param name="handler">The error handler which returns the result of the promise.</param>
339 /// <returns>New promise.</returns>
339 /// <returns>New promise.</returns>
340 public IPromise<T> Error(Func<Exception,T> handler) {
340 public IPromise<T> Error(Func<Exception,T> handler) {
341 if (handler == null)
341 if (handler == null)
342 return this;
342 return this;
343
343
344 var medium = new Promise<T>(this);
344 var medium = new Promise<T>(this);
345
345
346 AddHandler(null, handler, null, medium, true);
346 AddHandler(null, handler, null, medium, true);
347
347
348 return medium;
348 return medium;
349 }
349 }
350
350
351 /// <summary>
351 /// <summary>
352 /// ΠŸΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ‚ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.
352 /// ΠŸΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ‚ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.
353 /// </summary>
353 /// </summary>
354 /// <typeparam name="TNew">Новый Ρ‚ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°.</typeparam>
354 /// <typeparam name="TNew">Новый Ρ‚ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°.</typeparam>
355 /// <param name="mapper">ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.</param>
355 /// <param name="mapper">ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.</param>
356 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
356 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
357 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
357 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
358 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ исходного обСщания.</returns>
358 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ исходного обСщания.</returns>
359 /// <param name = "cancel"></param>
359 /// <param name = "cancel"></param>
360 public IPromise<TNew> Then<TNew>(Func<T, TNew> mapper, Func<Exception,TNew> error, Action cancel) {
360 public IPromise<TNew> Then<TNew>(Func<T, TNew> mapper, Func<Exception,TNew> error, Action cancel) {
361 Safe.ArgumentNotNull(mapper, "mapper");
361 Safe.ArgumentNotNull(mapper, "mapper");
362
362
363 // создаСм ΠΏΡ€ΠΈΡ†Π΅ΠΏΠ»Π΅Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
363 // создаСм ΠΏΡ€ΠΈΡ†Π΅ΠΏΠ»Π΅Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
364 var medium = new Promise<TNew>(this);
364 var medium = new Promise<TNew>(this);
365
365
366 Action<T> resultHandler = result => medium.Resolve(mapper(result));
366 Action<T> resultHandler = result => medium.Resolve(mapper(result));
367 Func<Exception,T> errorHandler;
367 Func<Exception,T> errorHandler;
368 if (error != null)
368 if (error != null)
369 errorHandler = e => {
369 errorHandler = e => {
370 try {
370 try {
371 medium.Resolve(error(e));
371 medium.Resolve(error(e));
372 } catch (Exception e2) {
372 } catch (Exception e2) {
373 // Π² случаС ошибки Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅
373 // Π² случаС ошибки Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅
374 medium.Reject(e2);
374 medium.Reject(e2);
375 }
375 }
376 return default(T);
376 return default(T);
377 };
377 };
378 else
378 else
379 errorHandler = e => {
379 errorHandler = e => {
380 medium.Reject(e);
380 medium.Reject(e);
381 return default(T);
381 return default(T);
382 };
382 };
383
383
384 Action cancelHandler;
384 Action cancelHandler;
385 if (cancel != null)
385 if (cancel != null)
386 cancelHandler = () => {
386 cancelHandler = () => {
387 cancel();
387 cancel();
388 medium.Cancel();
388 medium.Cancel();
389 };
389 };
390 else
390 else
391 cancelHandler = medium.Cancel;
391 cancelHandler = medium.Cancel;
392
392
393
393
394 AddHandler(
394 AddHandler(
395 resultHandler,
395 resultHandler,
396 errorHandler,
396 errorHandler,
397 cancelHandler,
397 cancelHandler,
398 null,
398 null,
399 true
399 true
400 );
400 );
401
401
402 return medium;
402 return medium;
403 }
403 }
404
404
405 public IPromise<TNew> Then<TNew>(Func<T, TNew> mapper, Func<Exception,TNew> error) {
405 public IPromise<TNew> Then<TNew>(Func<T, TNew> mapper, Func<Exception,TNew> error) {
406 return Then(mapper, error, null);
406 return Then(mapper, error, null);
407 }
407 }
408
408
409 public IPromise<TNew> Then<TNew>(Func<T, TNew> mapper) {
409 public IPromise<TNew> Then<TNew>(Func<T, TNew> mapper) {
410 return Then(mapper, null, null);
410 return Then(mapper, null, null);
411 }
411 }
412
412
413 /// <summary>
413 /// <summary>
414 /// БцСпляСт нСсколько аснхронных ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ. Указанная асинхронная опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½Π° послС
414 /// БцСпляСт нСсколько аснхронных ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ. Указанная асинхронная опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½Π° послС
415 /// выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ, Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ использован для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ
415 /// выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ, Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ использован для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ
416 /// Π½ΠΎΠ²ΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.
416 /// Π½ΠΎΠ²ΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.
417 /// </summary>
417 /// </summary>
418 /// <typeparam name="TNew">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</typeparam>
418 /// <typeparam name="TNew">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</typeparam>
419 /// <param name="chained">Асинхронная опСрация, которая Π΄ΠΎΠ»ΠΆΠ½Π° Π±ΡƒΠ΄Π΅Ρ‚ Π½Π°Ρ‡Π°Ρ‚ΡŒΡΡ послС выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ.</param>
419 /// <param name="chained">Асинхронная опСрация, которая Π΄ΠΎΠ»ΠΆΠ½Π° Π±ΡƒΠ΄Π΅Ρ‚ Π½Π°Ρ‡Π°Ρ‚ΡŒΡΡ послС выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ.</param>
420 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
420 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
421 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Ρ‚Π΅ΠΊΡƒΠ΅Ρ‰ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
421 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Ρ‚Π΅ΠΊΡƒΠ΅Ρ‰ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
422 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ аснхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</returns>
422 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ аснхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</returns>
423 /// <param name = "cancel"></param>
423 /// <param name = "cancel"></param>
424 public IPromise<TNew> Chain<TNew>(Func<T, IPromise<TNew>> chained, Func<Exception,IPromise<TNew>> error, Action cancel) {
424 public IPromise<TNew> Chain<TNew>(Func<T, IPromise<TNew>> chained, Func<Exception,IPromise<TNew>> error, Action cancel) {
425
425
426 Safe.ArgumentNotNull(chained, "chained");
426 Safe.ArgumentNotNull(chained, "chained");
427
427
428 // ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ‚ связывания Π΅Ρ‰Π΅ Π½Π΅ Π½Π°Ρ‡Π°Ρ‚Π° асинхронная опСрация, поэтому Π½ΡƒΠΆΠ½ΠΎ
428 // ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ‚ связывания Π΅Ρ‰Π΅ Π½Π΅ Π½Π°Ρ‡Π°Ρ‚Π° асинхронная опСрация, поэтому Π½ΡƒΠΆΠ½ΠΎ
429 // ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ посрСдника, ΠΊ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠΎΠ΄Π²Ρ‹Π·ΡΠ²Π°Ρ‚ΡŒΡΡ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ.
429 // ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ посрСдника, ΠΊ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠΎΠ΄Π²Ρ‹Π·ΡΠ²Π°Ρ‚ΡŒΡΡ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ.
430 // ΠΊΠΎΠ³Π΄Π° Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° Ρ€Π΅Π°Π»ΡŒΠ½Π°Ρ асинхронная опСрация, ΠΎΠ½Π° ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ ΠΊ посрСднику, Ρ‡Ρ‚ΠΎΠ±Ρ‹
430 // ΠΊΠΎΠ³Π΄Π° Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° Ρ€Π΅Π°Π»ΡŒΠ½Π°Ρ асинхронная опСрация, ΠΎΠ½Π° ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ ΠΊ посрСднику, Ρ‡Ρ‚ΠΎΠ±Ρ‹
431 // ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· Π½Π΅Π³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Ρ€Π°Π±ΠΎΡ‚Ρ‹.
431 // ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· Π½Π΅Π³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Ρ€Π°Π±ΠΎΡ‚Ρ‹.
432 var medium = new Promise<TNew>(this);
432 var medium = new Promise<TNew>(this);
433
433
434 Action<T> resultHandler = delegate(T result) {
434 Action<T> resultHandler = delegate(T result) {
435 if (medium.IsCancelled)
435 if (medium.IsCancelled)
436 return;
436 return;
437
437
438 var promise = chained(result);
438 var promise = chained(result);
439
439
440 promise.On(
440 promise.On(
441 medium.Resolve,
441 medium.Resolve,
442 medium.Reject,
442 medium.Reject,
443 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
443 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
444 );
444 );
445
445
446 // notify chained operation that it's not needed anymore
446 // notify chained operation that it's not needed anymore
447 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
447 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
448 // зависит IsExclusive
448 // зависит IsExclusive
449 medium.On(
449 medium.On(
450 null,
450 null,
451 null,
451 null,
452 () => {
452 () => {
453 if (promise.IsExclusive)
453 if (promise.IsExclusive)
454 promise.Cancel();
454 promise.Cancel();
455 }
455 }
456 );
456 );
457 };
457 };
458
458
459 Func<Exception,T> errorHandler;
459 Func<Exception,T> errorHandler;
460
460
461 if (error != null)
461 if (error != null)
462 errorHandler = delegate(Exception e) {
462 errorHandler = delegate(Exception e) {
463 try {
463 try {
464 var promise = error(e);
464 var promise = error(e);
465
465
466 promise.On(
466 promise.On(
467 medium.Resolve,
467 medium.Resolve,
468 medium.Reject,
468 medium.Reject,
469 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
469 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
470 );
470 );
471
471
472 // notify chained operation that it's not needed anymore
472 // notify chained operation that it's not needed anymore
473 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
473 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
474 // зависит IsExclusive
474 // зависит IsExclusive
475 medium.Cancelled(() => {
475 medium.Cancelled(() => {
476 if (promise.IsExclusive)
476 if (promise.IsExclusive)
477 promise.Cancel();
477 promise.Cancel();
478 });
478 });
479 } catch (Exception e2) {
479 } catch (Exception e2) {
480 medium.Reject(e2);
480 medium.Reject(e2);
481 }
481 }
482 return default(T);
482 return default(T);
483 };
483 };
484 else
484 else
485 errorHandler = err => {
485 errorHandler = err => {
486 medium.Reject(err);
486 medium.Reject(err);
487 return default(T);
487 return default(T);
488 };
488 };
489
489
490
490
491 Action cancelHandler;
491 Action cancelHandler;
492 if (cancel != null)
492 if (cancel != null)
493 cancelHandler = () => {
493 cancelHandler = () => {
494 if (cancel != null)
494 if (cancel != null)
495 cancel();
495 cancel();
496 medium.Cancel();
496 medium.Cancel();
497 };
497 };
498 else
498 else
499 cancelHandler = medium.Cancel;
499 cancelHandler = medium.Cancel;
500
500
501 AddHandler(
501 AddHandler(
502 resultHandler,
502 resultHandler,
503 errorHandler,
503 errorHandler,
504 cancelHandler,
504 cancelHandler,
505 null,
505 null,
506 true
506 true
507 );
507 );
508
508
509 return medium;
509 return medium;
510 }
510 }
511
511
512 public IPromise<TNew> Chain<TNew>(Func<T, IPromise<TNew>> chained, Func<Exception,IPromise<TNew>> error) {
512 public IPromise<TNew> Chain<TNew>(Func<T, IPromise<TNew>> chained, Func<Exception,IPromise<TNew>> error) {
513 return Chain(chained, error, null);
513 return Chain(chained, error, null);
514 }
514 }
515
515
516 public IPromise<TNew> Chain<TNew>(Func<T, IPromise<TNew>> chained) {
516 public IPromise<TNew> Chain<TNew>(Func<T, IPromise<TNew>> chained) {
517 return Chain(chained, null, null);
517 return Chain(chained, null, null);
518 }
518 }
519
519
520 public IPromise<T> Cancelled(Action handler) {
520 public IPromise<T> Cancelled(Action handler) {
521 var medium = new Promise<T>(this);
521 var medium = new Promise<T>(this);
522 AddHandler(null, null, handler, medium, false);
522 AddHandler(null, null, handler, medium, false);
523 return medium;
523 return medium;
524 }
524 }
525
525
526 /// <summary>
526 /// <summary>
527 /// Adds the specified handler for all cases (success, error, cancel)
527 /// Adds the specified handler for all cases (success, error, cancel)
528 /// </summary>
528 /// </summary>
529 /// <param name="handler">The handler that will be called anyway</param>
529 /// <param name="handler">The handler that will be called anyway</param>
530 /// <returns>self</returns>
530 /// <returns>self</returns>
531 public IPromise<T> Anyway(Action handler) {
531 public IPromise<T> Anyway(Action handler) {
532 Safe.ArgumentNotNull(handler, "handler");
532 Safe.ArgumentNotNull(handler, "handler");
533
533
534 var medium = new Promise<T>(this);
534 var medium = new Promise<T>(this);
535
535
536 AddHandler(
536 AddHandler(
537 x => handler(),
537 x => handler(),
538 e => {
538 e => {
539 handler();
539 handler();
540 throw new TransientPromiseException(e);
540 throw new TransientPromiseException(e);
541 },
541 },
542 handler,
542 handler,
543 medium,
543 medium,
544 true
544 true
545 );
545 );
546
546
547 return medium;
547 return medium;
548 }
548 }
549
549
550 /// <summary>
550 /// <summary>
551 /// ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ обСщания ΠΊ Π½ΡƒΠΆΠ½ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ
551 /// ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ обСщания ΠΊ Π½ΡƒΠΆΠ½ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ
552 /// </summary>
552 /// </summary>
553 /// <typeparam name="T2"></typeparam>
553 /// <typeparam name="T2"></typeparam>
554 /// <returns></returns>
554 /// <returns></returns>
555 public IPromise<T2> Cast<T2>() {
555 public IPromise<T2> Cast<T2>() {
556 return Then(x => (T2)(object)x, null);
556 return Then(x => (T2)(object)x, null);
557 }
557 }
558
558
559 /// <summary>
559 /// <summary>
560 /// ДоТидаСтся ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ³ΠΎ обСщания ΠΈ Π² случаС успСха, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚
560 /// ДоТидаСтся ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ³ΠΎ обСщания ΠΈ Π² случаС успСха, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚
561 /// Π΅Π³ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС бросаСт ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.
561 /// Π΅Π³ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС бросаСт ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.
562 /// </summary>
562 /// </summary>
563 /// <remarks>
563 /// <remarks>
564 /// <para>
564 /// <para>
565 /// Если ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ обСщания Π±Ρ‹Π»ΠΎ ΠΏΡ€Π΅Ρ€Π²Π°Π½ΠΎ ΠΏΠΎ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚Ρƒ, это Π½Π΅ Π·Π½Π°Ρ‡ΠΈΡ‚,
565 /// Если ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ обСщания Π±Ρ‹Π»ΠΎ ΠΏΡ€Π΅Ρ€Π²Π°Π½ΠΎ ΠΏΠΎ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚Ρƒ, это Π½Π΅ Π·Π½Π°Ρ‡ΠΈΡ‚,
566 /// Ρ‡Ρ‚ΠΎ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±Ρ‹Π»ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½ΠΎ ΠΈΠ»ΠΈ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π² этом Ρ€ΠΎΠ΄Π΅, это Ρ‚ΠΎΠ»ΡŒΠΊΠΎ
566 /// Ρ‡Ρ‚ΠΎ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±Ρ‹Π»ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½ΠΎ ΠΈΠ»ΠΈ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π² этом Ρ€ΠΎΠ΄Π΅, это Ρ‚ΠΎΠ»ΡŒΠΊΠΎ
567 /// ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π΅Π³ΠΎ Π½Π΅ доТдались, ΠΎΠ΄Π½Π°ΠΊΠΎ всС зарСгистрированныС
567 /// ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π΅Π³ΠΎ Π½Π΅ доТдались, ΠΎΠ΄Π½Π°ΠΊΠΎ всС зарСгистрированныС
568 /// ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, ΠΊΠ°ΠΊ Π±Ρ‹Π»ΠΈ Ρ‚Π°ΠΊ ΠΎΡΡ‚Π°Π»ΠΈΡΡŒ ΠΈ ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹, ΠΊΠΎΠ³Π΄Π°
568 /// ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, ΠΊΠ°ΠΊ Π±Ρ‹Π»ΠΈ Ρ‚Π°ΠΊ ΠΎΡΡ‚Π°Π»ΠΈΡΡŒ ΠΈ ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹, ΠΊΠΎΠ³Π΄Π°
569 /// ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
569 /// ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
570 /// </para>
570 /// </para>
571 /// <para>
571 /// <para>
572 /// Π’Π°ΠΊΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π²ΠΏΠΎΠ»Π½Π΅ ΠΎΠΏΡ€Π°Π²Π΄Π°Π½ΠΎ ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΡ‚Π΅Ρ‡ΡŒ
572 /// Π’Π°ΠΊΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π²ΠΏΠΎΠ»Π½Π΅ ΠΎΠΏΡ€Π°Π²Π΄Π°Π½ΠΎ ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΡ‚Π΅Ρ‡ΡŒ
573 /// Π² Ρ‚ΠΎΡ‚ ΠΌΠΎΠΌΠ΅Π½Ρ‚, ΠΊΠΎΠ³Π΄Π° Π½Π°Ρ‡Π°Π»Π°ΡΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ², ΠΈ
573 /// Π² Ρ‚ΠΎΡ‚ ΠΌΠΎΠΌΠ΅Π½Ρ‚, ΠΊΠΎΠ³Π΄Π° Π½Π°Ρ‡Π°Π»Π°ΡΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ², ΠΈ
574 /// ΠΊ Ρ‚ΠΎΠΌΡƒ ΠΆΠ΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡ‚ΠΎΡΡ‚ΡŒ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ ΠΈ Π΅Π³ΠΎ
574 /// ΠΊ Ρ‚ΠΎΠΌΡƒ ΠΆΠ΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡ‚ΠΎΡΡ‚ΡŒ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ ΠΈ Π΅Π³ΠΎ
575 /// ΠΎΡ‚ΠΊΠ»ΠΎΠ½Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ Π½Π΅ΠΏΡ€ΠΎΠ³Π½ΠΎΠ·ΠΈΡ€ΡƒΠ΅ΠΌΠΎΠΌΡƒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρƒ.
575 /// ΠΎΡ‚ΠΊΠ»ΠΎΠ½Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ Π½Π΅ΠΏΡ€ΠΎΠ³Π½ΠΎΠ·ΠΈΡ€ΡƒΠ΅ΠΌΠΎΠΌΡƒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρƒ.
576 /// </para>
576 /// </para>
577 /// </remarks>
577 /// </remarks>
578 /// <param name="timeout">ВрСмя оТидания</param>
578 /// <param name="timeout">ВрСмя оТидания</param>
579 /// <returns>Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния обСщания</returns>
579 /// <returns>Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния обСщания</returns>
580 public T Join(int timeout) {
580 public T Join(int timeout) {
581 var evt = new ManualResetEvent(false);
581 var evt = new ManualResetEvent(false);
582 Anyway(() => evt.Set());
582 Anyway(() => evt.Set());
583
583
584 if (!evt.WaitOne(timeout, true))
584 if (!evt.WaitOne(timeout, true))
585 throw new TimeoutException();
585 throw new TimeoutException();
586
586
587 switch (m_state) {
587 switch (m_state) {
588 case SUCCEEDED_STATE:
588 case SUCCEEDED_STATE:
589 return m_result;
589 return m_result;
590 case CANCELLED_STATE:
590 case CANCELLED_STATE:
591 throw new OperationCanceledException();
591 throw new OperationCanceledException();
592 case REJECTED_STATE:
592 case REJECTED_STATE:
593 throw new TargetInvocationException(m_error);
593 throw new TargetInvocationException(m_error);
594 default:
594 default:
595 throw new ApplicationException(String.Format("Invalid promise state {0}", m_state));
595 throw new ApplicationException(String.Format("Invalid promise state {0}", m_state));
596 }
596 }
597 }
597 }
598
598
599 public T Join() {
599 public T Join() {
600 return Join(Timeout.Infinite);
600 return Join(Timeout.Infinite);
601 }
601 }
602
602
603 void AddHandler(Action<T> success, Func<Exception,T> error, Action cancel, Promise<T> medium, bool inc) {
603 void AddHandler(Action<T> success, Func<Exception,T> error, Action cancel, Promise<T> medium, bool inc) {
604 if (inc)
604 if (inc)
605 Interlocked.Increment(ref m_childrenCount);
605 Interlocked.Increment(ref m_childrenCount);
606
606
607 var handler = new HandlerDescriptor {
607 var handler = new HandlerDescriptor {
608 resultHandler = success,
608 resultHandler = success,
609 errorHandler = error,
609 errorHandler = error,
610 cancellHandler = cancel,
610 cancellHandler = cancel,
611 medium = medium
611 medium = medium
612 };
612 };
613
613
614 bool queued;
614 bool queued;
615
615
616 if (!IsResolved) {
616 if (!IsResolved) {
617 m_handlers.Enqueue(handler);
617 m_handlers.Enqueue(handler);
618 queued = true;
618 queued = true;
619 } else {
619 } else {
620 // the promise is in resolved state, just invoke the handled with minimum overhead
620 // the promise is in resolved state, just invoke the handled with minimum overhead
621 queued = false;
621 queued = false;
622 InvokeHandler(handler);
622 InvokeHandler(handler);
623 }
623 }
624
624
625 if (queued && IsResolved && m_handlers.TryDequeue(out handler))
625 if (queued && IsResolved && m_handlers.TryDequeue(out handler))
626 // if the promise have been resolved while we was adding handler to the queue
626 // if the promise have been resolved while we was adding handler to the queue
627 // we can't guarantee that someone is still processing it
627 // we can't guarantee that someone is still processing it
628 // therefore we will fetch a handler from the queue and execute it
628 // therefore we will fetch a handler from the queue and execute it
629 // note that fetched handler may be not the one that we have added
629 // note that fetched handler may be not the one that we have added
630 // even we can fetch no handlers at all :)
630 // even we can fetch no handlers at all :)
631 InvokeHandler(handler);
631 InvokeHandler(handler);
632 }
632 }
633
633
634 protected virtual void InvokeHandler(HandlerDescriptor handler) {
634 protected virtual void InvokeHandler(HandlerDescriptor handler) {
635 switch (m_state) {
635 switch (m_state) {
636 case SUCCEEDED_STATE:
636 case SUCCEEDED_STATE:
637 handler.Resolve(m_result);
637 handler.Resolve(m_result);
638 break;
638 break;
639 case REJECTED_STATE:
639 case REJECTED_STATE:
640 handler.Reject(m_error);
640 handler.Reject(m_error);
641 break;
641 break;
642 case CANCELLED_STATE:
642 case CANCELLED_STATE:
643 handler.Cancel();
643 handler.Cancel();
644 break;
644 break;
645 default:
645 default:
646 // do nothing
646 // do nothing
647 return;
647 return;
648 }
648 }
649 }
649 }
650
650
651 void OnStateChanged() {
651 void OnStateChanged() {
652 HandlerDescriptor handler;
652 HandlerDescriptor handler;
653 while (m_handlers.TryDequeue(out handler))
653 while (m_handlers.TryDequeue(out handler))
654 InvokeHandler(handler);
654 InvokeHandler(handler);
655 }
655 }
656
656
657 public bool IsExclusive {
657 public bool IsExclusive {
658 get {
658 get {
659 return m_childrenCount <= 1;
659 return m_childrenCount <= 1;
660 }
660 }
661 }
661 }
662
662
663 /// <summary>
663 /// <summary>
664 /// ΠžΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ нСсколько ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ являСтся массив Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
664 /// ΠžΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ нСсколько ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ являСтся массив Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
665 /// Если хотябы ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚ΠΎ Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ Ρ‚ΠΎΠΆΠ΅ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
665 /// Если хотябы ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚ΠΎ Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ Ρ‚ΠΎΠΆΠ΅ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
666 /// ΠŸΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ Π½ΠΎΠ²ΠΎΠ³ΠΎ обСщания, ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅ обСщания Ρ‚Π°ΠΊΠΆΠ΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Ρ‹, Ссли Π½ΠΈΠΊΡ‚ΠΎ большС Π½Π° Π½ΠΈΡ… Π½Π΅ подписан.
666 /// ΠŸΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ Π½ΠΎΠ²ΠΎΠ³ΠΎ обСщания, ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅ обСщания Ρ‚Π°ΠΊΠΆΠ΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Ρ‹, Ссли Π½ΠΈΠΊΡ‚ΠΎ большС Π½Π° Π½ΠΈΡ… Π½Π΅ подписан.
667 /// </summary>
667 /// </summary>
668 /// <param name="promises">Бписок ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ. Если список пустой, Ρ‚ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ возвращаСтся ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹ΠΌ.</param>
668 /// <param name="promises">Бписок ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ. Если список пустой, Ρ‚ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ возвращаСтся ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹ΠΌ.</param>
669 /// <returns>ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰Π΅Π΅ Π² сСбС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.</returns>
669 /// <returns>ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰Π΅Π΅ Π² сСбС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.</returns>
670 /// <exception cref="ArgumentNullException"><paramref name="promises"/> Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ null</exception>
670 /// <exception cref="ArgumentNullException"><paramref name="promises"/> Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ null</exception>
671 public static IPromise<T[]> CreateComposite(IList<IPromise<T>> promises) {
671 public static IPromise<T[]> CreateComposite(IList<IPromise<T>> promises) {
672 if (promises == null)
672 if (promises == null)
673 throw new ArgumentNullException();
673 throw new ArgumentNullException();
674
674
675 // создаСм аккумулятор для Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² ΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
675 // создаСм аккумулятор для Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² ΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
676 var result = new T[promises.Count];
676 var result = new T[promises.Count];
677 var promise = new Promise<T[]>();
677 var promise = new Promise<T[]>();
678
678
679 // special case
679 // special case
680 if (promises.Count == 0) {
680 if (promises.Count == 0) {
681 promise.Resolve(result);
681 promise.Resolve(result);
682 return promise;
682 return promise;
683 }
683 }
684
684
685 int pending = promises.Count;
685 int pending = promises.Count;
686
686
687 for (int i = 0; i < promises.Count; i++) {
687 for (int i = 0; i < promises.Count; i++) {
688 var dest = i;
688 var dest = i;
689
689
690 if (promises[i] != null) {
690 if (promises[i] != null) {
691 promises[i].Then(
691 promises[i].Then(
692 x => {
692 x => {
693 result[dest] = x;
693 result[dest] = x;
694 if (Interlocked.Decrement(ref pending) == 0)
694 if (Interlocked.Decrement(ref pending) == 0)
695 promise.Resolve(result);
695 promise.Resolve(result);
696 },
696 },
697 e => {
697 e => {
698 promise.Reject(e);
698 promise.Reject(e);
699 return default(T);
699 return default(T);
700 }
700 }
701 );
701 );
702 } else {
702 } else {
703 if (Interlocked.Decrement(ref pending) == 0)
703 if (Interlocked.Decrement(ref pending) == 0)
704 promise.Resolve(result);
704 promise.Resolve(result);
705 }
705 }
706 }
706 }
707
707
708 promise.Cancelled(
708 promise.Cancelled(
709 () => {
709 () => {
710 foreach (var d in promises)
710 foreach (var d in promises)
711 if (d != null && d.IsExclusive)
711 if (d != null && d.IsExclusive)
712 d.Cancel();
712 d.Cancel();
713 }
713 }
714 );
714 );
715
715
716 return promise;
716 return promise;
717 }
717 }
718
718
719 /// <summary>
719 /// <summary>
720 /// ΠžΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ нСсколько ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ. Π Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ
720 /// ΠžΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ нСсколько ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ. Π Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ
721 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ всСх ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ. ΠŸΡ€ΠΈ этом Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹Π΅ значСния ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ
721 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ всСх ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ. ΠŸΡ€ΠΈ этом Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹Π΅ значСния ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ
722 /// ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΡƒΡŽΡ‚ΡΡ.
722 /// ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΡƒΡŽΡ‚ΡΡ.
723 /// </summary>
723 /// </summary>
724 /// <param name="promises">ΠšΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΡ ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΠ±ΡŠΠ΅Π΄Π΅Π½Π΅Π½Ρ‹ Π² ΠΎΠ΄Π½ΠΎ.</param>
724 /// <param name="promises">ΠšΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΡ ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΠ±ΡŠΠ΅Π΄Π΅Π½Π΅Π½Ρ‹ Π² ΠΎΠ΄Π½ΠΎ.</param>
725 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰Π΅Π΅ Π² сСбС ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅.</returns>
725 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰Π΅Π΅ Π² сСбС ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅.</returns>
726 /// <remarks>
726 /// <remarks>
727 /// Если Π² ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΈ Π²ΡΡ‚Ρ€Π΅Ρ‡Π°ΡŽΡŒΡΡ <c>null</c>, Ρ‚ΠΎ ΠΎΠ½ΠΈ Π²ΠΎΡΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹Π΅ обСщания.
727 /// Если Π² ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΈ Π²ΡΡ‚Ρ€Π΅Ρ‡Π°ΡŽΡŒΡΡ <c>null</c>, Ρ‚ΠΎ ΠΎΠ½ΠΈ Π²ΠΎΡΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹Π΅ обСщания.
728 /// </remarks>
728 /// </remarks>
729 public static IPromise CreateComposite(ICollection<IPromise> promises) {
729 public static IPromise CreateComposite(ICollection<IPromise> promises) {
730 if (promises == null)
730 if (promises == null)
731 throw new ArgumentNullException();
731 throw new ArgumentNullException();
732 if (promises.Count == 0)
732 if (promises.Count == 0)
733 return Promise<object>.ResultToPromise(null);
733 return Promise<object>.ResultToPromise(null);
734
734
735 int countdown = promises.Count;
735 int countdown = promises.Count;
736
736
737 var result = new Promise<object>();
737 var result = new Promise<object>();
738
738
739 foreach (var d in promises) {
739 foreach (var d in promises) {
740 if (d == null) {
740 if (d == null) {
741 if (Interlocked.Decrement(ref countdown) == 0)
741 if (Interlocked.Decrement(ref countdown) == 0)
742 result.Resolve(null);
742 result.Resolve(null);
743 } else {
743 } else {
744 d.Then(() => {
744 d.Then(() => {
745 if (Interlocked.Decrement(ref countdown) == 0)
745 if (Interlocked.Decrement(ref countdown) == 0)
746 result.Resolve(null);
746 result.Resolve(null);
747 });
747 });
748 }
748 }
749 }
749 }
750
750
751 result.Cancelled(() => {
751 result.Cancelled(() => {
752 foreach (var d in promises)
752 foreach (var d in promises)
753 if (d != null && d.IsExclusive)
753 if (d != null && d.IsExclusive)
754 d.Cancel();
754 d.Cancel();
755 });
755 });
756
756
757 return result;
757 return result;
758 }
758 }
759
759
760 public static Promise<T> ResultToPromise(T result) {
760 public static Promise<T> ResultToPromise(T result) {
761 var p = new Promise<T>();
761 var p = new Promise<T>();
762 p.Resolve(result);
762 p.Resolve(result);
763 return p;
763 return p;
764 }
764 }
765
765
766 public static Promise<T> ExceptionToPromise(Exception error) {
766 public static Promise<T> ExceptionToPromise(Exception error) {
767 if (error == null)
767 if (error == null)
768 throw new ArgumentNullException();
768 throw new ArgumentNullException();
769
769
770 var p = new Promise<T>();
770 var p = new Promise<T>();
771 p.Reject(error);
771 p.Reject(error);
772 return p;
772 return p;
773 }
773 }
774
774
775 #region IPromiseBase explicit implementation
775 #region IPromiseBase explicit implementation
776
776
777 IPromise IPromise.Then(Action success, Action<Exception> error, Action cancel) {
777 IPromise IPromise.Then(Action success, Action<Exception> error, Action cancel) {
778 return Then(
778 return Then(
779 success != null ? new Action<T>(x => success()) : null,
779 success != null ? new Action<T>(x => success()) : null,
780 error != null ? new Func<Exception,T>(e => {
780 error != null ? new Func<Exception,T>(e => {
781 error(e);
781 error(e);
782 return default(T);
782 return default(T);
783 }) : null,
783 }) : null,
784 cancel
784 cancel
785 );
785 );
786 }
786 }
787
787
788 IPromise IPromise.Then(Action success, Action<Exception> error) {
788 IPromise IPromise.Then(Action success, Action<Exception> error) {
789 return Then(
789 return Then(
790 success != null ? new Action<T>(x => success()) : null,
790 success != null ? new Action<T>(x => success()) : null,
791 error != null ? new Func<Exception,T>(e => {
791 error != null ? new Func<Exception,T>(e => {
792 error(e);
792 error(e);
793 return default(T);
793 return default(T);
794 }) : null
794 }) : null
795 );
795 );
796 }
796 }
797
797
798 IPromise IPromise.Then(Action success) {
798 IPromise IPromise.Then(Action success) {
799 Safe.ArgumentNotNull(success, "success");
799 Safe.ArgumentNotNull(success, "success");
800 return Then(x => success());
800 return Then(x => success());
801 }
801 }
802
802
803 IPromise IPromise.Chain(Func<IPromise> chained, Func<Exception,IPromise> error, Action cancel) {
803 IPromise IPromise.Chain(Func<IPromise> chained, Func<Exception,IPromise> error, Action cancel) {
804 return ChainNoResult(chained, error, cancel);
804 return ChainNoResult(chained, error, cancel);
805 }
805 }
806
806
807 IPromise ChainNoResult(Func<IPromise> chained, Func<Exception,IPromise> error, Action cancel) {
807 IPromise ChainNoResult(Func<IPromise> chained, Func<Exception,IPromise> error, Action cancel) {
808 Safe.ArgumentNotNull(chained, "chained");
808 Safe.ArgumentNotNull(chained, "chained");
809
809
810 var medium = new Promise<object>(this);
810 var medium = new Promise<object>(this);
811
811
812 Action<T> resultHandler = delegate {
812 Action<T> resultHandler = delegate {
813 if (medium.IsCancelled)
813 if (medium.IsCancelled)
814 return;
814 return;
815
815
816 var promise = chained();
816 var promise = chained();
817
817
818 promise.On(
818 promise.On(
819 medium.Resolve,
819 medium.Resolve,
820 medium.Reject,
820 medium.Reject,
821 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
821 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
822 );
822 );
823
823
824 // notify chained operation that it's not needed anymore
824 // notify chained operation that it's not needed anymore
825 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
825 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
826 // зависит IsExclusive
826 // зависит IsExclusive
827 medium.Cancelled(() => {
827 medium.Cancelled(() => {
828 if (promise.IsExclusive)
828 if (promise.IsExclusive)
829 promise.Cancel();
829 promise.Cancel();
830 });
830 });
831 };
831 };
832
832
833 Func<Exception,T> errorHandler;
833 Func<Exception,T> errorHandler;
834
834
835 if (error != null)
835 if (error != null)
836 errorHandler = delegate(Exception e) {
836 errorHandler = delegate(Exception e) {
837 try {
837 try {
838 var promise = error(e);
838 var promise = error(e);
839
839
840 promise.On(
840 promise.On(
841 medium.Resolve,
841 medium.Resolve,
842 medium.Reject,
842 medium.Reject,
843 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
843 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
844 );
844 );
845
845
846 // notify chained operation that it's not needed anymore
846 // notify chained operation that it's not needed anymore
847 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
847 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
848 // зависит IsExclusive
848 // зависит IsExclusive
849 medium.Cancelled(() => {
849 medium.Cancelled(() => {
850 if (promise.IsExclusive)
850 if (promise.IsExclusive)
851 promise.Cancel();
851 promise.Cancel();
852 });
852 });
853 } catch (Exception e2) {
853 } catch (Exception e2) {
854 medium.Reject(e2);
854 medium.Reject(e2);
855 }
855 }
856 return default(T);
856 return default(T);
857 };
857 };
858 else
858 else
859 errorHandler = err => {
859 errorHandler = err => {
860 medium.Reject(err);
860 medium.Reject(err);
861 return default(T);
861 return default(T);
862 };
862 };
863
863
864
864
865 Action cancelHandler;
865 Action cancelHandler;
866 if (cancel != null)
866 if (cancel != null)
867 cancelHandler = () => {
867 cancelHandler = () => {
868 if (cancel != null)
868 if (cancel != null)
869 cancel();
869 cancel();
870 medium.Cancel();
870 medium.Cancel();
871 };
871 };
872 else
872 else
873 cancelHandler = medium.Cancel;
873 cancelHandler = medium.Cancel;
874
874
875 AddHandler(
875 AddHandler(
876 resultHandler,
876 resultHandler,
877 errorHandler,
877 errorHandler,
878 cancelHandler,
878 cancelHandler,
879 null,
879 null,
880 true
880 true
881 );
881 );
882
882
883 return medium;
883 return medium;
884 }
884 }
885
885
886 IPromise IPromise.Chain(Func<IPromise> chained, Func<Exception,IPromise> error) {
886 IPromise IPromise.Chain(Func<IPromise> chained, Func<Exception,IPromise> error) {
887 return ChainNoResult(chained, error, null);
887 return ChainNoResult(chained, error, null);
888 }
888 }
889
889
890 IPromise IPromise.Chain(Func<IPromise> chained) {
890 IPromise IPromise.Chain(Func<IPromise> chained) {
891 return ChainNoResult(chained, null, null);
891 return ChainNoResult(chained, null, null);
892 }
892 }
893
893
894
894
895 void IPromise.On(Action success, Action<Exception> error, Action cancel) {
895 void IPromise.On(Action success, Action<Exception> error, Action cancel) {
896 On(x => success(), error, cancel);
896 On(success != null ? new Action<T>(x => success()) : null, error, cancel);
897 }
897 }
898
898
899 void IPromise.On(Action success, Action<Exception> error) {
899 void IPromise.On(Action success, Action<Exception> error) {
900 On(x => success(), error, null);
900 On(x => success(), error, null);
901 }
901 }
902
902
903 void IPromise.On(Action success) {
903 void IPromise.On(Action success) {
904 On(x => success(), null, null);
904 On(x => success(), null, null);
905 }
905 }
906
906
907 IPromise IPromise.Error(Action<Exception> error) {
907 IPromise IPromise.Error(Action<Exception> error) {
908 return Error(error);
908 return Error(error);
909 }
909 }
910
910
911 IPromise IPromise.Anyway(Action handler) {
911 IPromise IPromise.Anyway(Action handler) {
912 return Anyway(handler);
912 return Anyway(handler);
913 }
913 }
914
914
915 IPromise IPromise.Cancelled(Action handler) {
915 IPromise IPromise.Cancelled(Action handler) {
916 return Cancelled(handler);
916 return Cancelled(handler);
917 }
917 }
918
918
919 void IPromise.Join() {
919 void IPromise.Join() {
920 Join();
920 Join();
921 }
921 }
922
922
923 void IPromise.Join(int timeout) {
923 void IPromise.Join(int timeout) {
924 Join(timeout);
924 Join(timeout);
925 }
925 }
926
926
927 #endregion
927 #endregion
928
928
929
929
930
930
931 }
931 }
932 }
932 }
General Comments 0
You need to be logged in to leave comments. Login now