comparison Implab/Promise`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.Diagnostics;
3 using System.Reflection;
4 using Implab.Parallels;
5
6 namespace Implab {
7 public class Promise<T> : AbstractEvent<IResolvable<T>>, IPromise<T> {
8
9 class ResolvableSignal : IResolvable<T> {
10 public Signal Signal { get; private set; }
11 public ResolvableSignal() {
12 Signal = new Signal();
13 }
14
15
16 public void Reject(Exception error) {
17 Signal.Set();
18 }
19
20 public void Resolve(T result) {
21 Signal.Set();
22 }
23 }
24
25 class ResolvableWrapper : IResolvable<T> {
26 readonly IResolvable m_resolvable;
27 public ResolvableWrapper(IResolvable resolvable) {
28 m_resolvable = resolvable;
29 }
30
31 public void Reject(Exception reason) {
32 m_resolvable.Reject(reason);
33 }
34
35 public void Resolve(T value) {
36 m_resolvable.Resolve();
37 }
38 }
39
40 PromiseState m_state;
41
42 T m_result;
43
44 Exception m_error;
45
46 public bool IsRejected {
47 get {
48 return m_state == PromiseState.Rejected;
49 }
50 }
51
52 public bool IsFulfilled {
53 get {
54 return m_state == PromiseState.Fulfilled;
55 }
56 }
57
58 public Exception RejectReason {
59 get {
60 return m_error;
61 }
62 }
63
64
65 internal void ResolvePromise(T result) {
66 if (BeginTransit()) {
67 m_result = result;
68 m_state = PromiseState.Fulfilled;
69 CompleteTransit();
70 }
71 }
72
73 internal void RejectPromise(Exception reason) {
74 if (BeginTransit()) {
75 m_error = reason;
76 m_state = PromiseState.Rejected;
77 CompleteTransit();
78 }
79 }
80
81
82 #region implemented abstract members of AbstractPromise
83
84 protected override void SignalHandler(IResolvable<T> handler) {
85 switch (m_state) {
86 case PromiseState.Fulfilled:
87 handler.Resolve(m_result);
88 break;
89 case PromiseState.Rejected:
90 handler.Reject(RejectReason);
91 break;
92 default:
93 throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", m_state));
94 }
95 }
96
97 protected void WaitResult(int timeout) {
98 if (!(IsResolved || GetFulfillSignal().Wait(timeout)))
99 throw new TimeoutException();
100 }
101
102 protected Signal GetFulfillSignal() {
103 var next = new ResolvableSignal();
104 Then(next);
105 return next.Signal;
106 }
107
108 #endregion
109
110 public Type ResultType {
111 get {
112 return typeof(void);
113 }
114 }
115
116
117 protected void Rethrow() {
118 if (m_error is OperationCanceledException)
119 throw new OperationCanceledException("Operation cancelled", m_error);
120 else
121 throw new TargetInvocationException(m_error);
122 }
123
124 public void Then(IResolvable<T> next) {
125 AddHandler(next);
126 }
127
128 public void Then(IResolvable next) {
129 AddHandler(new ResolvableWrapper(next));
130 }
131
132 public IPromise<T2> Cast<T2>() {
133 return (IPromise<T2>)this;
134 }
135
136 void IPromise.Join() {
137 Join();
138 }
139
140 void IPromise.Join(int timeout) {
141 Join(timeout);
142 }
143
144 public T Join() {
145 WaitResult(-1);
146 if (IsRejected)
147 Rethrow();
148 return m_result;
149 }
150
151 public T Join(int timeout) {
152 WaitResult(timeout);
153 if (IsRejected)
154 Rethrow();
155 return m_result;
156 }
157 }
158 }
159