##// END OF EJS Templates
Добавлена метка v3.0.6 для набора изменений 547a2fc0d93e
Добавлена метка v3.0.6 для набора изменений 547a2fc0d93e

File last commit:

r248:5cb4826c2c2a v3
r261:05a87f575512 v3
Show More
PromiseAll`1.cs
89 lines | 2.5 KiB | text/x-csharp | CSharpLexer
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;
}
}
}