247
|
1 using System;
|
|
2 using System.Diagnostics;
|
|
3 using System.Reflection;
|
|
4 using Implab.Parallels;
|
|
5
|
|
6 namespace Implab {
|
|
7 public class AbstractPromise<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
|
|
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 Resolve(T result) {
|
|
66 if (BeginTransit())
|
|
67 CompleteResolve();
|
|
68 }
|
|
69
|
|
70 internal void Reject(Exception reason) {
|
|
71 if (BeginTransit()) {
|
|
72 m_error = reason;
|
|
73 m_state = PromiseState.Rejected;
|
|
74 CompleteTransit();
|
|
75 }
|
|
76 }
|
|
77
|
|
78
|
|
79 #region implemented abstract members of AbstractPromise
|
|
80
|
|
81 protected override void SignalHandler(IResolvable<T> handler) {
|
|
82 switch (m_state) {
|
|
83 case PromiseState.Fulfilled:
|
|
84 handler.Resolve(m_result);
|
|
85 break;
|
|
86 case PromiseState.Rejected:
|
|
87 handler.Reject(RejectReason);
|
|
88 break;
|
|
89 default:
|
|
90 throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", m_state));
|
|
91 }
|
|
92 }
|
|
93
|
|
94 protected override Signal GetFulfillSignal() {
|
|
95 var next = new ResolvableSignal();
|
|
96 Then(next);
|
|
97 return next.Signal;
|
|
98 }
|
|
99
|
|
100 #endregion
|
|
101
|
|
102 protected void CompleteResolve() {
|
|
103 m_state = PromiseState.Fulfilled;
|
|
104 CompleteTransit();
|
|
105 }
|
|
106
|
|
107 public Type ResultType {
|
|
108 get {
|
|
109 return typeof(void);
|
|
110 }
|
|
111 }
|
|
112
|
|
113
|
|
114 protected void Rethrow() {
|
|
115 Debug.Assert(m_error != null);
|
|
116 if (m_error is OperationCanceledException)
|
|
117 throw new OperationCanceledException("Operation cancelled", m_error);
|
|
118 else
|
|
119 throw new TargetInvocationException(m_error);
|
|
120 }
|
|
121
|
|
122 public void Then(IResolvable<T> next) {
|
|
123 AddHandler(next);
|
|
124 }
|
|
125
|
|
126 public void Then(IResolvable next) {
|
|
127 AddHandler(new ResolvableWrapper(next));
|
|
128 }
|
|
129
|
|
130 public IPromise<T2> Cast<T2>() {
|
|
131 return (IPromise<T2>)this;
|
|
132 }
|
|
133
|
|
134 void IPromise.Join() {
|
|
135 WaitResult(-1);
|
|
136 if (IsRejected)
|
|
137 Rethrow();
|
|
138 }
|
|
139
|
|
140 void IPromise.Join(int timeout) {
|
|
141 WaitResult(timeout);
|
|
142 if (IsRejected)
|
|
143 Rethrow();
|
|
144 }
|
|
145
|
|
146 public T Join() {
|
|
147 WaitResult(-1);
|
|
148 if (IsRejected)
|
|
149 Rethrow();
|
|
150 return m_result;
|
|
151 }
|
|
152
|
|
153 public T Join(int timeout) {
|
|
154 WaitResult(timeout);
|
|
155 if (IsRejected)
|
|
156 Rethrow();
|
|
157 return m_result;
|
|
158 }
|
|
159 }
|
|
160 }
|
|
161
|