@@ -328,6 +328,59 namespace Implab.Test { | |||||
328 | Assert.IsTrue(flags[1]); |
|
328 | Assert.IsTrue(flags[1]); | |
329 | Assert.IsTrue(flags[2]); |
|
329 | Assert.IsTrue(flags[2]); | |
330 | } |
|
330 | } | |
|
331 | ||||
|
332 | [TestMethod] | |||
|
333 | public void ChainedCancel1Test() { | |||
|
334 | // ΠΏΡΠΈ ΠΎΡΠΌΠ΅Π½Π΅ ΡΡΠ΅ΠΏΠ»Π΅Π½Π½ΠΎΠΉ Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΠΎΠΉ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ Π²ΡΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ | |||
|
335 | // Π·Π°Π²Π΅ΡΡΠ°ΡΡΡΡ ΠΎΡΠΈΠ±ΠΊΠΎΠΉ OperationCanceledException | |||
|
336 | var p = PromiseHelper | |||
|
337 | .Sleep(1, "Hi, HAL!") | |||
|
338 | .Chain(x => { | |||
|
339 | // Π·Π°ΠΏΡΡΠΊΠ°Π΅ΠΌ Π΄Π²Π΅ Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΡΠ΅ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ | |||
|
340 | var result = PromiseHelper.Sleep(1000, "HEM ENABLED!!!"); | |||
|
341 | // Π²ΡΠΎΡΠ°Ρ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΡ ΠΎΡΠΌΠ΅Π½ΡΠ΅Ρ ΠΏΠ΅ΡΠ²ΡΡ Π΄ΠΎ Π·Π°Π²Π΅ΡΡΠ΅Π½ΠΈΡ | |||
|
342 | PromiseHelper | |||
|
343 | .Sleep(100, "HAL, STOP!") | |||
|
344 | .Then(() => result.Cancel()); | |||
|
345 | return result; | |||
|
346 | }); | |||
|
347 | try { | |||
|
348 | p.Join(); | |||
|
349 | } catch (TargetInvocationException err) { | |||
|
350 | Assert.IsTrue(err.InnerException is OperationCanceledException); | |||
331 | } |
|
351 | } | |
332 | } |
|
352 | } | |
333 |
|
353 | |||
|
354 | [TestMethod] | |||
|
355 | public void ChainedCancel2Test() { | |||
|
356 | // ΠΏΡΠΈ ΠΎΡΠΌΠ΅Π½Π΅ ΡΠ΅ΠΏΠΎΡΠΊΠΈ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΉ, Π²Π»ΠΎΠΆΠ΅Π½Π½ΡΠ΅ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ ΡΠ°ΠΊΠΆΠ΅ Π΄ΠΎΠ»ΠΆΠ½Ρ ΠΎΡΠΌΠ΅Π½ΡΡΡΡΡ | |||
|
357 | IPromiseBase p = null; | |||
|
358 | var pSurvive = new Promise<bool>(); | |||
|
359 | var hemStarted = new ManualResetEvent(false); | |||
|
360 | p = PromiseHelper | |||
|
361 | .Sleep(1, "Hi, HAL!") | |||
|
362 | .Chain(x => { | |||
|
363 | hemStarted.Set(); | |||
|
364 | // Π·Π°ΠΏΡΡΠΊΠ°Π΅ΠΌ Π΄Π²Π΅ Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΡΠ΅ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ | |||
|
365 | var result = PromiseHelper | |||
|
366 | .Sleep(1000, "HEM ENABLED!!!") | |||
|
367 | .Then(s => pSurvive.Resolve(false)); | |||
|
368 | ||||
|
369 | result | |||
|
370 | .Cancelled(() => pSurvive.Resolve(true)); | |||
|
371 | ||||
|
372 | return result; | |||
|
373 | }); | |||
|
374 | ||||
|
375 | hemStarted.WaitOne(); | |||
|
376 | p.Cancel(); | |||
|
377 | ||||
|
378 | try { | |||
|
379 | p.Join(); | |||
|
380 | } catch (OperationCanceledException) { | |||
|
381 | Assert.IsTrue(pSurvive.Join()); | |||
|
382 | } | |||
|
383 | } | |||
|
384 | } | |||
|
385 | } | |||
|
386 |
1 | NO CONTENT: modified file, binary diff hidden |
|
NO CONTENT: modified file, binary diff hidden |
@@ -8,14 +8,13 namespace Implab | |||||
8 | public interface IPromise<T>: IPromiseBase |
|
8 | public interface IPromise<T>: IPromiseBase | |
9 | { |
|
9 | { | |
10 |
|
10 | |||
11 | T Join(); |
|
11 | new T Join(); | |
12 |
|
12 | new T Join(int timeout); | ||
13 | T Join(int timeout); |
|
|||
14 |
|
13 | |||
15 | IPromise<T> Then(ResultHandler<T> success, ErrorHandler error); |
|
14 | IPromise<T> Then(ResultHandler<T> success, ErrorHandler error); | |
16 | IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error); |
|
15 | IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error); | |
17 | IPromise<T> Then(ResultHandler<T> success); |
|
16 | IPromise<T> Then(ResultHandler<T> success); | |
18 | IPromise<T> Error(ErrorHandler error); |
|
17 | new IPromise<T> Error(ErrorHandler error); | |
19 | IPromise<T> Error(ErrorHandler<T> error); |
|
18 | IPromise<T> Error(ErrorHandler<T> error); | |
20 |
|
19 | |||
21 | IPromise<T2> Map<T2>(ResultMapper<T,T2> mapper, ErrorHandler error); |
|
20 | IPromise<T2> Map<T2>(ResultMapper<T,T2> mapper, ErrorHandler error); | |
@@ -24,9 +23,9 namespace Implab | |||||
24 | IPromise<T2> Chain<T2>(ChainedOperation<T, T2> chained, ErrorHandler error); |
|
23 | IPromise<T2> Chain<T2>(ChainedOperation<T, T2> chained, ErrorHandler error); | |
25 | IPromise<T2> Chain<T2>(ChainedOperation<T, T2> chained); |
|
24 | IPromise<T2> Chain<T2>(ChainedOperation<T, T2> chained); | |
26 |
|
25 | |||
27 | IPromise<T> Cancelled(Action handler); |
|
26 | new IPromise<T> Cancelled(Action handler); | |
28 | IPromise<T> Finally(Action handler); |
|
27 | new IPromise<T> Finally(Action handler); | |
29 | IPromise<T> Anyway(Action handler); |
|
28 | new IPromise<T> Anyway(Action handler); | |
30 |
|
29 | |||
31 | } |
|
30 | } | |
32 | } |
|
31 | } |
@@ -23,8 +23,15 namespace Implab { | |||||
23 |
|
23 | |||
24 | IPromiseBase Then(Action success,ErrorHandler error); |
|
24 | IPromiseBase Then(Action success,ErrorHandler error); | |
25 | IPromiseBase Then(Action success); |
|
25 | IPromiseBase Then(Action success); | |
|
26 | IPromiseBase Error(ErrorHandler error); | |||
|
27 | IPromiseBase Anyway(Action handler); | |||
|
28 | IPromiseBase Finally(Action handler); | |||
|
29 | IPromiseBase Cancelled(Action handler); | |||
26 |
|
30 | |||
27 | IPromise<T> Cast<T>(); |
|
31 | IPromise<T> Cast<T>(); | |
28 |
|
32 | |||
|
33 | void Join(); | |||
|
34 | void Join(int timeout); | |||
|
35 | ||||
29 | } |
|
36 | } | |
30 | } |
|
37 | } |
@@ -86,7 +86,6 namespace Implab { | |||||
86 | const int RejectedState = 3; |
|
86 | const int RejectedState = 3; | |
87 | const int CancelledState = 4; |
|
87 | const int CancelledState = 4; | |
88 |
|
88 | |||
89 | readonly IPromiseBase m_parent; |
|
|||
90 | readonly bool m_cancellable; |
|
89 | readonly bool m_cancellable; | |
91 |
|
90 | |||
92 | int m_childrenCount = 0; |
|
91 | int m_childrenCount = 0; | |
@@ -102,12 +101,15 namespace Implab { | |||||
102 |
|
101 | |||
103 | public Promise(IPromiseBase parent, bool cancellable) { |
|
102 | public Promise(IPromiseBase parent, bool cancellable) { | |
104 | m_cancellable = cancellable; |
|
103 | m_cancellable = cancellable; | |
105 |
|
|
104 | if (parent != null) | |
|
105 | AddHandler( | |||
|
106 | null, | |||
|
107 | null, | |||
|
108 | () => { | |||
|
109 | if (parent.IsExclusive) | |||
|
110 | parent.Cancel(); | |||
106 | } |
|
111 | } | |
107 |
|
112 | ); | ||
108 | void InternalCancel() { |
|
|||
109 | // don't try to cancel parent :) |
|
|||
110 | Cancel(false); |
|
|||
111 | } |
|
113 | } | |
112 |
|
114 | |||
113 | bool BeginTransit() { |
|
115 | bool BeginTransit() { | |
@@ -159,6 +161,16 namespace Implab { | |||||
159 | } |
|
161 | } | |
160 |
|
162 | |||
161 | /// <summary> |
|
163 | /// <summary> | |
|
164 | /// ΠΡΠΏΠΎΠ»Π½ΡΠ΅Ρ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅, ΡΠΎΠΎΠ±ΡΠ°Ρ ΠΎΠ± ΡΡΠΏΠ΅ΡΠ½ΠΎΠΌ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ. Π Π΅Π·ΡΠ»ΡΡΠ°ΡΠΎΠΌ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ Π±ΡΠ΄Π΅Ρ ΠΏΡΡΡΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΡ. | |||
|
165 | /// </summary> | |||
|
166 | /// <remarks> | |||
|
167 | /// ΠΠ°Π½Π½ΡΠΉ Π²Π°ΡΠΈΠ°Π½Ρ ΡΠ΄ΠΎΠ±Π΅Π½ Π² ΡΠ»ΡΡΠ°ΡΡ , ΠΊΠΎΠ³Π΄Π° ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ΅Π½ ΡΠ°ΠΊΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ, Π½Π΅ΠΆΠ΅Π»ΠΈ ΠΏΠΎΠ»ΡΡΠ΅Π½Π½ΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅. | |||
|
168 | /// </remarks> | |||
|
169 | public void Resolve() { | |||
|
170 | Resolve(default(T)); | |||
|
171 | } | |||
|
172 | ||||
|
173 | /// <summary> | |||
162 | /// ΠΡΠΏΠΎΠ»Π½ΡΠ΅Ρ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅, ΡΠΎΠΎΠ±ΡΠ°Ρ ΠΎΠ± ΠΎΡΠΈΠ±ΠΊΠ΅ |
|
174 | /// ΠΡΠΏΠΎΠ»Π½ΡΠ΅Ρ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅, ΡΠΎΠΎΠ±ΡΠ°Ρ ΠΎΠ± ΠΎΡΠΈΠ±ΠΊΠ΅ | |
163 | /// </summary> |
|
175 | /// </summary> | |
164 | /// <remarks> |
|
176 | /// <remarks> | |
@@ -185,7 +197,18 namespace Implab { | |||||
185 | /// </summary> |
|
197 | /// </summary> | |
186 | /// <returns><c>true</c> ΠΠΏΠ΅ΡΠ°ΡΠΈΡ Π±ΡΠ»Π° ΠΎΡΠΌΠ΅Π½Π΅Π½Π°, ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ Π½Π΅ Π±ΡΠ΄ΡΡ Π²ΡΠ·Π²Π°Π½Ρ.<c>false</c> ΠΎΡΠΌΠ΅Π½Π° Π½Π΅ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π°, ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ ΡΠΆΠ΅ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΈ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ ΠΎΡΡΠ°Π±ΠΎΡΠ°Π»ΠΈ.</returns> |
|
198 | /// <returns><c>true</c> ΠΠΏΠ΅ΡΠ°ΡΠΈΡ Π±ΡΠ»Π° ΠΎΡΠΌΠ΅Π½Π΅Π½Π°, ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ Π½Π΅ Π±ΡΠ΄ΡΡ Π²ΡΠ·Π²Π°Π½Ρ.<c>false</c> ΠΎΡΠΌΠ΅Π½Π° Π½Π΅ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π°, ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ ΡΠΆΠ΅ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΈ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ ΠΎΡΡΠ°Π±ΠΎΡΠ°Π»ΠΈ.</returns> | |
187 | public bool Cancel() { |
|
199 | public bool Cancel() { | |
188 | return Cancel(true); |
|
200 | if (BeginTransit()) { | |
|
201 | CompleteTransit(CancelledState); | |||
|
202 | OnStateChanged(); | |||
|
203 | return true; | |||
|
204 | } else { | |||
|
205 | return false; | |||
|
206 | } | |||
|
207 | } | |||
|
208 | ||||
|
209 | // ΡΠ΄Π΅Π»Π°Π½ΠΎ Π΄Π»Ρ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΠΌΠΎΠ³ΠΎ ΡΠΈΠΏΠ° void | |||
|
210 | protected void InternalCancel() { | |||
|
211 | Cancel(); | |||
189 | } |
|
212 | } | |
190 |
|
213 | |||
191 | /// <summary> |
|
214 | /// <summary> | |
@@ -229,13 +252,11 namespace Implab { | |||||
229 | return medium; |
|
252 | return medium; | |
230 | } |
|
253 | } | |
231 |
|
254 | |||
232 | public IPromiseBase Then(Action success,ErrorHandler error) |
|
255 | public IPromiseBase Then(Action success, ErrorHandler error) { | |
233 | { |
|
|||
234 | return Then(x => success(), error); |
|
256 | return Then(x => success(), error); | |
235 | } |
|
257 | } | |
236 |
|
258 | |||
237 | public IPromiseBase Then(Action success) |
|
259 | public IPromiseBase Then(Action success) { | |
238 | { |
|
|||
239 | return Then(x => success()); |
|
260 | return Then(x => success()); | |
240 | } |
|
261 | } | |
241 |
|
262 | |||
@@ -338,7 +359,7 namespace Implab { | |||||
338 | if (handler == null) |
|
359 | if (handler == null) | |
339 | return this; |
|
360 | return this; | |
340 |
|
361 | |||
341 | var medium = new Promise<T>(); |
|
362 | var medium = new Promise<T>(this,true); | |
342 |
|
363 | |||
343 | AddHandler( |
|
364 | AddHandler( | |
344 | x => { |
|
365 | x => { | |
@@ -377,7 +398,7 namespace Implab { | |||||
377 | throw new ArgumentNullException("mapper"); |
|
398 | throw new ArgumentNullException("mapper"); | |
378 |
|
399 | |||
379 | // ΡΠΎΠ·Π΄Π°Π΅ΠΌ ΠΏΡΠΈΡΠ΅ΠΏΠ»Π΅Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ |
|
400 | // ΡΠΎΠ·Π΄Π°Π΅ΠΌ ΠΏΡΠΈΡΠ΅ΠΏΠ»Π΅Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ | |
380 | var chained = new Promise<TNew>(); |
|
401 | var chained = new Promise<TNew>(this,true); | |
381 |
|
402 | |||
382 | ResultHandler<T> resultHandler = result => chained.Resolve(mapper(result)); |
|
403 | ResultHandler<T> resultHandler = result => chained.Resolve(mapper(result)); | |
383 | ErrorHandler errorHandler = delegate(Exception e) { |
|
404 | ErrorHandler errorHandler = delegate(Exception e) { | |
@@ -427,12 +448,21 namespace Implab { | |||||
427 |
|
448 | |||
428 | var promise = chained(result); |
|
449 | var promise = chained(result); | |
429 |
|
450 | |||
430 | // notify chained operation that it's not needed |
|
|||
431 | medium.Cancelled(() => promise.Cancel()); |
|
|||
432 | promise.Then( |
|
451 | promise.Then( | |
433 | x => medium.Resolve(x), |
|
452 | x => medium.Resolve(x), | |
434 | e => medium.Reject(e) |
|
453 | e => medium.Reject(e) | |
435 | ); |
|
454 | ); | |
|
455 | ||||
|
456 | // notify chained operation that it's not needed anymore | |||
|
457 | // ΠΏΠΎΡΡΠ΄ΠΎΠΊ Π²ΡΠ·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΠΎΡ ΡΡΠΎΠ³ΠΎ | |||
|
458 | // Π·Π°Π²ΠΈΡΠΈΡ IsExclusive | |||
|
459 | medium.Cancelled(() => { | |||
|
460 | if(promise.IsExclusive) | |||
|
461 | promise.Cancel(); | |||
|
462 | }); | |||
|
463 | ||||
|
464 | // Π²Π½Π΅ΡΠ½ΡΡ ΠΎΡΠΌΠ΅Π½Π° ΡΠ²ΡΠ·Π°Π½Π½ΠΎΠΉ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ ΡΠ°ΡΡΠΌΠ°ΡΡΠΈΠ²Π°Π΅ΡΡΡ ΠΊΠ°ΠΊ ΠΎΡΠΈΠ±ΠΊΠ° | |||
|
465 | promise.Cancelled(() => medium.Reject(new OperationCanceledException())); | |||
436 | }; |
|
466 | }; | |
437 |
|
467 | |||
438 | ErrorHandler errorHandler = delegate(Exception e) { |
|
468 | ErrorHandler errorHandler = delegate(Exception e) { | |
@@ -531,6 +561,7 namespace Implab { | |||||
531 | } |
|
561 | } | |
532 |
|
562 | |||
533 | void AddHandler(ResultHandler<T> success, ErrorHandler error, Action cancel) { |
|
563 | void AddHandler(ResultHandler<T> success, ErrorHandler error, Action cancel) { | |
|
564 | if (success != null || error != null) | |||
534 | Interlocked.Increment(ref m_childrenCount); |
|
565 | Interlocked.Increment(ref m_childrenCount); | |
535 |
|
566 | |||
536 | HandlerDescriptor handler = new HandlerDescriptor { |
|
567 | HandlerDescriptor handler = new HandlerDescriptor { | |
@@ -588,20 +619,6 namespace Implab { | |||||
588 | } |
|
619 | } | |
589 | } |
|
620 | } | |
590 |
|
621 | |||
591 | protected bool Cancel(bool dependencies) { |
|
|||
592 | if (BeginTransit()) { |
|
|||
593 | CompleteTransit(CancelledState); |
|
|||
594 | OnStateChanged(); |
|
|||
595 |
|
||||
596 | if (dependencies && m_parent != null && m_parent.IsExclusive) |
|
|||
597 | m_parent.Cancel(); |
|
|||
598 |
|
||||
599 | return true; |
|
|||
600 | } else { |
|
|||
601 | return false; |
|
|||
602 | } |
|
|||
603 | } |
|
|||
604 |
|
||||
605 | /// <summary> |
|
622 | /// <summary> | |
606 | /// ΠΠ±ΡΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ, ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠΎΠΌ ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ ΡΠ²Π»ΡΠ΅ΡΡΡ ΠΌΠ°ΡΡΠΈΠ² ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠΎΠ² Π΄ΡΡΠ³ΠΈΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΉ. |
|
623 | /// ΠΠ±ΡΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ, ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠΎΠΌ ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ ΡΠ²Π»ΡΠ΅ΡΡΡ ΠΌΠ°ΡΡΠΈΠ² ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠΎΠ² Π΄ΡΡΠ³ΠΈΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΉ. | |
607 | /// ΠΡΠ»ΠΈ Ρ ΠΎΡΡΠ±Ρ ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΠΏΠ΅ΡΠ΅Π΄Π°Π½Π½ΡΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΉ Π½Π΅ Π±ΡΠ΄Π΅Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΎ, ΡΠΎ Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅ΡΠ΅Π½ΠΈΠ΅ ΡΠΎΠΆΠ΅ Π½Π΅ Π±ΡΠ΄Π΅Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΎ. |
|
624 | /// ΠΡΠ»ΠΈ Ρ ΠΎΡΡΠ±Ρ ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΠΏΠ΅ΡΠ΅Π΄Π°Π½Π½ΡΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΉ Π½Π΅ Π±ΡΠ΄Π΅Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΎ, ΡΠΎ Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅ΡΠ΅Π½ΠΈΠ΅ ΡΠΎΠΆΠ΅ Π½Π΅ Π±ΡΠ΄Π΅Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΎ. | |
@@ -629,6 +646,7 namespace Implab { | |||||
629 | for (int i = 0; i < promises.Count; i++) { |
|
646 | for (int i = 0; i < promises.Count; i++) { | |
630 | var dest = i; |
|
647 | var dest = i; | |
631 |
|
648 | |||
|
649 | if (promises[i] != null) { | |||
632 | promises[i].Then( |
|
650 | promises[i].Then( | |
633 | x => { |
|
651 | x => { | |
634 | result[dest] = x; |
|
652 | result[dest] = x; | |
@@ -637,12 +655,16 namespace Implab { | |||||
637 | }, |
|
655 | }, | |
638 | e => promise.Reject(e) |
|
656 | e => promise.Reject(e) | |
639 | ); |
|
657 | ); | |
|
658 | } else { | |||
|
659 | if (Interlocked.Decrement(ref pending) == 0) | |||
|
660 | promise.Resolve(result); | |||
|
661 | } | |||
640 | } |
|
662 | } | |
641 |
|
663 | |||
642 | promise.Cancelled( |
|
664 | promise.Cancelled( | |
643 | () => { |
|
665 | () => { | |
644 | foreach(var d in promises) |
|
666 | foreach (var d in promises) | |
645 | if(d.IsExclusive) |
|
667 | if (d != null && d.IsExclusive) | |
646 | d.Cancel(); |
|
668 | d.Cancel(); | |
647 | } |
|
669 | } | |
648 | ); |
|
670 | ); | |
@@ -650,6 +672,47 namespace Implab { | |||||
650 | return promise; |
|
672 | return promise; | |
651 | } |
|
673 | } | |
652 |
|
674 | |||
|
675 | /// <summary> | |||
|
676 | /// ΠΠ±ΡΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ. Π Π΅Π·ΡΠ»ΡΡΠΈΡΡΡΡΠ΅Π΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ Π±ΡΠ΄Π΅Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡΠΈ | |||
|
677 | /// Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Π²ΡΠ΅Ρ ΡΠΊΠ°Π·Π°Π½Π½ΡΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΉ. ΠΡΠΈ ΡΡΠΎΠΌ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΠΌΡΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΡ ΠΏΠ΅ΡΠ²ΠΈΡΠ½ΡΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΉ | |||
|
678 | /// ΠΈΠ³Π½ΠΎΡΠΈΡΡΡΡΡΡ. | |||
|
679 | /// </summary> | |||
|
680 | /// <param name="promises">ΠΠΎΠ»Π»Π΅ΠΊΡΠΈΡ ΠΏΠ΅ΡΠ²ΠΈΡΠ½ΡΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΉ, ΠΊΠΎΡΠΎΡΡΠ΅ Π±ΡΠ΄ΡΡ ΠΎΠ±ΡΠ΅Π΄Π΅Π½Π΅Π½Ρ Π² ΠΎΠ΄Π½ΠΎ.</param> | |||
|
681 | /// <returns>ΠΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅, ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½ΡΡΡΠ΅Π΅ Π² ΡΠ΅Π±Π΅ ΠΏΠ΅ΡΠ΅Π΄Π°Π½Π½ΡΠ΅.</returns> | |||
|
682 | /// <remarks> | |||
|
683 | /// ΠΡΠ»ΠΈ Π² ΠΊΠΎΠ»Π»Π΅ΠΊΡΠΈΠΈ Π²ΡΡΡΠ΅ΡΠ°ΡΡΡΡ <c>null</c>, ΡΠΎ ΠΎΠ½ΠΈ Π²ΠΎΡΠΏΡΠΈΠ½ΠΈΠΌΠ°ΡΡΡΡ ΠΊΠ°ΠΊ Π²ΡΠΏΠΎΠ»Π½Π΅Π½Π½ΡΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΡ. | |||
|
684 | /// </remarks> | |||
|
685 | public static IPromiseBase CreateComposite(ICollection<IPromiseBase> promises) { | |||
|
686 | if (promises == null) | |||
|
687 | throw new ArgumentNullException(); | |||
|
688 | if (promises.Count == 0) | |||
|
689 | return Promise<object>.ResultToPromise(null); | |||
|
690 | ||||
|
691 | int countdown = promises.Count; | |||
|
692 | ||||
|
693 | var result = new Promise<object>(); | |||
|
694 | ||||
|
695 | foreach (var d in promises) { | |||
|
696 | if (d == null) { | |||
|
697 | if (Interlocked.Decrement(ref countdown) == 0) | |||
|
698 | result.Resolve(null); | |||
|
699 | } else { | |||
|
700 | d.Then(() => { | |||
|
701 | if (Interlocked.Decrement(ref countdown) == 0) | |||
|
702 | result.Resolve(null); | |||
|
703 | }); | |||
|
704 | } | |||
|
705 | } | |||
|
706 | ||||
|
707 | result.Cancelled(() => { | |||
|
708 | foreach (var d in promises) | |||
|
709 | if (d != null && d.IsExclusive) | |||
|
710 | d.Cancel(); | |||
|
711 | }); | |||
|
712 | ||||
|
713 | return result; | |||
|
714 | } | |||
|
715 | ||||
653 | public static Promise<T> ResultToPromise(T result) { |
|
716 | public static Promise<T> ResultToPromise(T result) { | |
654 | var p = new Promise<T>(); |
|
717 | var p = new Promise<T>(); | |
655 | p.Resolve(result); |
|
718 | p.Resolve(result); | |
@@ -665,5 +728,35 namespace Implab { | |||||
665 | return p; |
|
728 | return p; | |
666 | } |
|
729 | } | |
667 |
|
730 | |||
|
731 | #region IPromiseBase explicit implementation | |||
|
732 | ||||
|
733 | IPromiseBase IPromiseBase.Error(ErrorHandler error) { | |||
|
734 | return Error(error); | |||
|
735 | } | |||
|
736 | ||||
|
737 | IPromiseBase IPromiseBase.Anyway(Action handler) { | |||
|
738 | return Anyway(handler); | |||
|
739 | } | |||
|
740 | ||||
|
741 | IPromiseBase IPromiseBase.Finally(Action handler) { | |||
|
742 | return Finally(handler); | |||
|
743 | } | |||
|
744 | ||||
|
745 | IPromiseBase IPromiseBase.Cancelled(Action handler) { | |||
|
746 | return Cancelled(handler); | |||
|
747 | } | |||
|
748 | ||||
|
749 | void IPromiseBase.Join() { | |||
|
750 | Join(); | |||
|
751 | } | |||
|
752 | ||||
|
753 | void IPromiseBase.Join(int timeout) { | |||
|
754 | Join(timeout); | |||
|
755 | } | |||
|
756 | ||||
|
757 | #endregion | |||
|
758 | ||||
|
759 | ||||
|
760 | ||||
668 | } |
|
761 | } | |
669 | } |
|
762 | } |
General Comments 0
You need to be logged in to leave comments.
Login now