annotate Implab/Promise.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 d82909310094
children 547a2fc0d93e
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.Diagnostics;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
4 using System.Reflection;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
5 using System.Threading.Tasks;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
6 using Implab.Parallels;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
7
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
8 namespace Implab {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
9 public class Promise : AbstractEvent<IResolvable>, IPromise {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
10 public static IDispatcher DefaultDispatcher {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
11 get {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
12 return ThreadPoolDispatcher.Instance;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
13 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
14 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
15
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
16 class ResolvableSignal : IResolvable {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
17 public Signal Signal { get; private set; }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
18 public ResolvableSignal() {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
19 Signal = new Signal();
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
20 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
21
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
22
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
23 public void Reject(Exception error) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
24 Signal.Set();
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
25 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
26
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
27 public void Resolve() {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
28 Signal.Set();
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
29 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
30 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
31
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
32 PromiseState m_state;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
33
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
34 Exception m_error;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
35
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
36 public bool IsRejected {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
37 get {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
38 return m_state == PromiseState.Rejected;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
39 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
40 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
41
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
42 public bool IsFulfilled {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
43 get {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
44 return m_state == PromiseState.Fulfilled;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
45 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
46 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
47
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
48 public Exception RejectReason {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
49 get {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
50 return m_error;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
51 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
52 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
53
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
54 internal Promise() {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
55
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
56 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
57
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
58 internal void ResolvePromise() {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
59 if (BeginTransit()) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
60 m_state = PromiseState.Fulfilled;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
61 CompleteTransit();
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
62 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
63 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
64
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
65 internal void RejectPromise(Exception reason) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
66 if (BeginTransit()) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
67 m_error = reason;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
68 m_state = PromiseState.Rejected;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
69 CompleteTransit();
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
70 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
71 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
72
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
73
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
74 #region implemented abstract members of AbstractPromise
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
75
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
76 protected override void SignalHandler(IResolvable handler) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
77 switch (m_state) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
78 case PromiseState.Fulfilled:
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
79 handler.Resolve();
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
80 break;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
81 case PromiseState.Rejected:
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
82 handler.Reject(RejectReason);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
83 break;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
84 default:
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
85 throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", m_state));
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
86 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
87 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
88
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
89 protected void WaitResult(int timeout) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
90 if (!(IsResolved || GetFulfillSignal().Wait(timeout)))
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
91 throw new TimeoutException();
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
92 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
93
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
94 protected Signal GetFulfillSignal() {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
95 var next = new ResolvableSignal();
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
96 Then(next);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
97 return next.Signal;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
98 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
99
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
100 #endregion
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
101
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
102
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
103 public Type ResultType {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
104 get {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
105 return typeof(void);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
106 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
107 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
108
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
109
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
110 protected void Rethrow() {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
111 Debug.Assert(m_error != null);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
112 if (m_error is OperationCanceledException)
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
113 throw new OperationCanceledException("Operation cancelled", m_error);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
114 else
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
115 throw new TargetInvocationException(m_error);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
116 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
117
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
118 public void Then(IResolvable next) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
119 AddHandler(next);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
120 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
121
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
122 public IPromise<T> Cast<T>() {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
123 throw new InvalidCastException();
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
124 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
125
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
126 public void Join() {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
127 WaitResult(-1);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
128 if (IsRejected)
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
129 Rethrow();
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
130 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
131
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
132 public void Join(int timeout) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
133 WaitResult(timeout);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
134 if (IsRejected)
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
135 Rethrow();
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
136 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
137
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
138 public static ResolvedPromise Resolve() {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
139 return new ResolvedPromise();
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
140 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
141
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
142 public static ResolvedPromise<T> Resolve<T>(T result) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
143 return new ResolvedPromise<T>(result);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
144 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
145
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
146 public static RejectedPromise Reject(Exception reason) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
147 return new RejectedPromise(reason);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
148 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
149
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
150 public static RejectedPromise<T> Reject<T>(Exception reason) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
151 return new RejectedPromise<T>(reason);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
152 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
153
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
154 public static IPromise Create(PromiseExecutor executor) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
155 Safe.ArgumentNotNull(executor, nameof(executor));
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
156
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
157 var p = new Promise();
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
158 var d = new Deferred(p, DefaultDispatcher);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
159
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
160 try {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
161 executor(d);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
162 } catch (Exception e) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
163 d.Reject(e);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
164 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
165
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
166 return d.Promise;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
167 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
168
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
169 public static IPromise<T> Create<T>(PromiseExecutor<T> executor) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
170 Safe.ArgumentNotNull(executor, nameof(executor));
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
171
249
d82909310094 Implab.Test moved to xunit
cin
parents: 248
diff changeset
172 var d = new Deferred<T>();
248
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
173
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
174 try {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
175 executor(d);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
176 } catch (Exception e) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
177 d.Reject(e);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
178 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
179
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
180 return d.Promise;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
181 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
182
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
183 public static IPromise All(IEnumerable<IPromise> promises) {
249
d82909310094 Implab.Test moved to xunit
cin
parents: 248
diff changeset
184 var d = new Deferred();
248
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
185 var all = new PromiseAll(d);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
186 foreach (var promise in promises) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
187 all.AddPromise(promise);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
188 if (all.Done)
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
189 break;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
190 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
191 all.Complete();
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
192 return all.ResultPromise;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
193 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
194
249
d82909310094 Implab.Test moved to xunit
cin
parents: 248
diff changeset
195 public static IPromise<T[]> All<T>(IEnumerable<IPromise<T>> promises, Func<T, IPromise> cleanup = null, Action cancel = null) {
d82909310094 Implab.Test moved to xunit
cin
parents: 248
diff changeset
196 var d = new Deferred<T[]>();
248
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
197 var all = new PromiseAll<T>(d, cleanup, cancel);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
198 foreach (var promise in promises) {
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
199 all.AddPromise(promise);
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
200 if (all.Done)
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
201 break;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
202 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
203 all.Complete();
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
204 return all.ResultPromise;
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
205 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
206 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
207 }
5cb4826c2c2a Added awaiters to promises
cin
parents:
diff changeset
208