annotate Implab/PromiseAll`1.cs @ 255:b00441e04738 v3

Adde workaround to the behaviour of the logical operations stack in conjuction with async/await methods
author cin
date Wed, 04 Apr 2018 15:38:48 +0300
parents 5cb4826c2c2a
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
248
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
1 using System;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
2 using System.Collections.Generic;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
3 using System.Linq;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
4 using System.Threading;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
5
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
6 namespace Implab {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
7 class PromiseAll<T> : IResolvable {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
8
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
9 int m_count;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
10
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
11 readonly List<IPromise<T>> m_promises = new List<IPromise<T>>();
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
12
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
13 readonly Deferred<T[]> m_deferred;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
14
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
15 IPromise<T[]> m_result;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
16
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
17 readonly Func<T, IPromise> m_cleanup;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
18
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
19 readonly Action m_cancel;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
20
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
21 public bool Done {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
22 get { return m_deferred.Promise.IsResolved && m_cleanup == null; }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
23 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
24
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
25 public IPromise<T[]> ResultPromise {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
26 get { return m_result; }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
27 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
28
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
29 public void AddPromise(IPromise<T> promise) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
30 Interlocked.Increment(ref m_count);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
31 promise.Then(this);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
32 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
33
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
34 public PromiseAll(Deferred<T[]> deferred, Func<T, IPromise> cleanup, Action cancel) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
35 m_deferred = deferred;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
36 m_cancel = cancel;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
37 m_cleanup = cleanup;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
38 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
39
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
40 public void Resolve() {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
41 if (Interlocked.Decrement(ref m_count) == 0)
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
42 m_deferred.Resolve(GetResults());
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
43 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
44
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
45 public void Reject(Exception error) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
46 m_deferred.Reject(error);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
47 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
48
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
49 public void Complete() {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
50 if (m_cancel != null || m_cleanup != null)
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
51 m_result = m_deferred.Promise.Catch(CleanupResults);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
52 else
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
53 m_result = m_deferred.Promise;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
54 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
55
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
56 IPromise<T[]> CleanupResults(Exception reason) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
57 var errors = new List<Exception>();
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
58 errors.Add(reason);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
59
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
60 if (m_cancel != null)
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
61 try {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
62 m_cancel();
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
63 } catch (Exception e) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
64 errors.Add(e);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
65 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
66
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
67 if (m_cleanup != null) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
68 return Promise.All(
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
69 m_promises.Select(p => p
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
70 .Then(m_cleanup, e => { })
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
71 .Catch(e => {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
72 errors.Add(e);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
73 })
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
74 )
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
75 ).Then<T[]>(new Func<T[]>(() => {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
76 throw new AggregateException(errors);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
77 }), (Func<Exception, T[]>)null);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
78 } else {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
79 return Promise.Reject<T[]>(errors.Count > 1 ? new AggregateException(errors) : reason);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
80 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
81 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
82
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
83 T[] GetResults() {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
84 var results = new T[m_promises.Count];
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
85 for (var i = 0; i < results.Length; i++)
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
86 results[i] = m_promises[i].Join();
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
87 return results;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
88 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
89 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
90 }