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