PromiseAll`1.cs
89 lines
| 2.5 KiB
| text/x-csharp
|
CSharpLexer
cin
|
r289 | 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; | |||
} | |||
} | |||
} |