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 }