Mercurial > pub > ImplabNet
comparison Implab/PromiseAll`1.cs @ 248:5cb4826c2c2a v3
Added awaiters to promises
Added static methods to Promise Resolve, Reject, All.
Updated promise helpers
| author | cin |
|---|---|
| date | Tue, 30 Jan 2018 01:37:17 +0300 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 247:fb70574741a1 | 248:5cb4826c2c2a |
|---|---|
| 1 using System; | |
| 2 using System.Collections.Generic; | |
| 3 using System.Linq; | |
| 4 using System.Threading; | |
| 5 | |
| 6 namespace Implab { | |
| 7 class PromiseAll<T> : IResolvable { | |
| 8 | |
| 9 int m_count; | |
| 10 | |
| 11 readonly List<IPromise<T>> m_promises = new List<IPromise<T>>(); | |
| 12 | |
| 13 readonly Deferred<T[]> m_deferred; | |
| 14 | |
| 15 IPromise<T[]> m_result; | |
| 16 | |
| 17 readonly Func<T, IPromise> m_cleanup; | |
| 18 | |
| 19 readonly Action m_cancel; | |
| 20 | |
| 21 public bool Done { | |
| 22 get { return m_deferred.Promise.IsResolved && m_cleanup == null; } | |
| 23 } | |
| 24 | |
| 25 public IPromise<T[]> ResultPromise { | |
| 26 get { return m_result; } | |
| 27 } | |
| 28 | |
| 29 public void AddPromise(IPromise<T> promise) { | |
| 30 Interlocked.Increment(ref m_count); | |
| 31 promise.Then(this); | |
| 32 } | |
| 33 | |
| 34 public PromiseAll(Deferred<T[]> deferred, Func<T, IPromise> cleanup, Action cancel) { | |
| 35 m_deferred = deferred; | |
| 36 m_cancel = cancel; | |
| 37 m_cleanup = cleanup; | |
| 38 } | |
| 39 | |
| 40 public void Resolve() { | |
| 41 if (Interlocked.Decrement(ref m_count) == 0) | |
| 42 m_deferred.Resolve(GetResults()); | |
| 43 } | |
| 44 | |
| 45 public void Reject(Exception error) { | |
| 46 m_deferred.Reject(error); | |
| 47 } | |
| 48 | |
| 49 public void Complete() { | |
| 50 if (m_cancel != null || m_cleanup != null) | |
| 51 m_result = m_deferred.Promise.Catch(CleanupResults); | |
| 52 else | |
| 53 m_result = m_deferred.Promise; | |
| 54 } | |
| 55 | |
| 56 IPromise<T[]> CleanupResults(Exception reason) { | |
| 57 var errors = new List<Exception>(); | |
| 58 errors.Add(reason); | |
| 59 | |
| 60 if (m_cancel != null) | |
| 61 try { | |
| 62 m_cancel(); | |
| 63 } catch (Exception e) { | |
| 64 errors.Add(e); | |
| 65 } | |
| 66 | |
| 67 if (m_cleanup != null) { | |
| 68 return Promise.All( | |
| 69 m_promises.Select(p => p | |
| 70 .Then(m_cleanup, e => { }) | |
| 71 .Catch(e => { | |
| 72 errors.Add(e); | |
| 73 }) | |
| 74 ) | |
| 75 ).Then<T[]>(new Func<T[]>(() => { | |
| 76 throw new AggregateException(errors); | |
| 77 }), (Func<Exception, T[]>)null); | |
| 78 } else { | |
| 79 return Promise.Reject<T[]>(errors.Count > 1 ? new AggregateException(errors) : reason); | |
| 80 } | |
| 81 } | |
| 82 | |
| 83 T[] GetResults() { | |
| 84 var results = new T[m_promises.Count]; | |
| 85 for (var i = 0; i < results.Length; i++) | |
| 86 results[i] = m_promises[i].Join(); | |
| 87 return results; | |
| 88 } | |
| 89 } | |
| 90 } |
