Mercurial > pub > ImplabNet
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/PromiseAll`1.cs Tue Jan 30 01:37:17 2018 +0300 @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; + +namespace Implab { + class PromiseAll<T> : IResolvable { + + int m_count; + + readonly List<IPromise<T>> m_promises = new List<IPromise<T>>(); + + readonly Deferred<T[]> m_deferred; + + IPromise<T[]> m_result; + + readonly Func<T, IPromise> m_cleanup; + + readonly Action m_cancel; + + public bool Done { + get { return m_deferred.Promise.IsResolved && m_cleanup == null; } + } + + public IPromise<T[]> ResultPromise { + get { return m_result; } + } + + public void AddPromise(IPromise<T> promise) { + Interlocked.Increment(ref m_count); + promise.Then(this); + } + + public PromiseAll(Deferred<T[]> deferred, Func<T, IPromise> cleanup, Action cancel) { + m_deferred = deferred; + m_cancel = cancel; + m_cleanup = cleanup; + } + + public void Resolve() { + if (Interlocked.Decrement(ref m_count) == 0) + m_deferred.Resolve(GetResults()); + } + + public void Reject(Exception error) { + m_deferred.Reject(error); + } + + public void Complete() { + if (m_cancel != null || m_cleanup != null) + m_result = m_deferred.Promise.Catch(CleanupResults); + else + m_result = m_deferred.Promise; + } + + IPromise<T[]> CleanupResults(Exception reason) { + var errors = new List<Exception>(); + errors.Add(reason); + + if (m_cancel != null) + try { + m_cancel(); + } catch (Exception e) { + errors.Add(e); + } + + if (m_cleanup != null) { + return Promise.All( + m_promises.Select(p => p + .Then(m_cleanup, e => { }) + .Catch(e => { + errors.Add(e); + }) + ) + ).Then<T[]>(new Func<T[]>(() => { + throw new AggregateException(errors); + }), (Func<Exception, T[]>)null); + } else { + return Promise.Reject<T[]>(errors.Count > 1 ? new AggregateException(errors) : reason); + } + } + + T[] GetResults() { + var results = new T[m_promises.Count]; + for (var i = 0; i < results.Length; i++) + results[i] = m_promises[i].Join(); + return results; + } + } +} \ No newline at end of file