Mercurial > pub > ImplabNet
view Implab/PromiseAll`1.cs @ 253:34df34841225 v3 v3.0.1-beta
Implab.Diagnostics drafts
author | cin |
---|---|
date | Mon, 12 Feb 2018 17:03:37 +0300 |
parents | 5cb4826c2c2a |
children |
line wrap: on
line source
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; } } }