comparison Implab/Promise.cs @ 138:f75cfa58e3d4 v2

added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
author cin
date Tue, 17 Feb 2015 18:16:26 +0300
parents 2573b562e328
children 8c0b95069066
comparison
equal deleted inserted replaced
137:238e15580926 138:f75cfa58e3d4
5 public class Promise : AbstractPromise<Promise.HandlerDescriptor>, IPromise, IDeferred { 5 public class Promise : AbstractPromise<Promise.HandlerDescriptor>, IPromise, IDeferred {
6 6
7 public struct HandlerDescriptor { 7 public struct HandlerDescriptor {
8 readonly Action m_success; 8 readonly Action m_success;
9 readonly Action<Exception> m_error; 9 readonly Action<Exception> m_error;
10 readonly Action m_cancel; 10 readonly Action<Exception> m_cancel;
11 readonly IDeferred m_deferred; 11 readonly IDeferred m_deferred;
12 12
13 public HandlerDescriptor(Action success, Action<Exception> error, Action cancel, IDeferred deferred) { 13 public HandlerDescriptor(Action success, Action<Exception> error, Action<Exception> cancel, IDeferred deferred) {
14 m_success = success; 14 m_success = success;
15 m_error = error; 15 m_error = error;
16 m_cancel = cancel; 16 m_cancel = cancel;
17 m_deferred = deferred; 17 m_deferred = deferred;
18 } 18 }
43 if (m_deferred != null) 43 if (m_deferred != null)
44 m_deferred.Reject(err); 44 m_deferred.Reject(err);
45 } 45 }
46 } 46 }
47 47
48 public void SignalCancel() { 48 public void SignalCancel(Exception reason) {
49 if (m_cancel != null) { 49 if (m_cancel != null) {
50 try { 50 try {
51 m_cancel(); 51 m_cancel(reason);
52 if (m_deferred != null) 52 if (m_deferred != null)
53 m_deferred.Resolve(); 53 m_deferred.Resolve();
54 } catch (Exception err) { 54 } catch (Exception err) {
55 SignalError(err); 55 SignalError(err);
56 } 56 }
57 } else if (reason != null && m_error != null) {
58 try {
59 m_error(new OperationCanceledException("The operation was canceled.", reason));
60 if (m_deferred != null)
61 m_deferred.Resolve();
62 } catch (Exception err) {
63 SignalError(err);
64 }
57 } else { 65 } else {
58 if (m_deferred != null) 66 if (m_deferred != null)
59 m_deferred.Cancel(); 67 m_deferred.Cancel(reason);
60 } 68 }
61 } 69 }
62 } 70 }
63 71
64 public void Resolve() { 72 public void Resolve() {
78 86
79 protected override void SignalError(HandlerDescriptor handler, Exception error) { 87 protected override void SignalError(HandlerDescriptor handler, Exception error) {
80 handler.SignalError(error); 88 handler.SignalError(error);
81 } 89 }
82 90
83 protected override void SignalCancelled(HandlerDescriptor handler) { 91 protected override void SignalCancelled(HandlerDescriptor handler, Exception reason) {
84 handler.SignalCancel(); 92 handler.SignalCancel(reason);
85 } 93 }
86 94
87 protected override void Listen(PromiseEventType events, Action handler) { 95 protected override void Listen(PromiseEventType events, Action handler) {
88 AddHandler(new HandlerDescriptor( 96 AddHandler(new HandlerDescriptor(
89 events.HasFlag(PromiseEventType.Success) ? handler : null, 97 events.HasFlag(PromiseEventType.Success) ? handler : null,
90 events.HasFlag(PromiseEventType.Error) ? new Action<Exception>(err => handler()) : null, 98 events.HasFlag(PromiseEventType.Error) ? new Action<Exception>(err => handler()) : null,
91 events.HasFlag(PromiseEventType.Cancelled) ? handler : null, 99 events.HasFlag(PromiseEventType.Cancelled) ? new Action<Exception>(reason => handler()) : null,
92 null 100 null
93 )); 101 ));
94 } 102 }
95 103
96 #endregion 104 #endregion
100 get { 108 get {
101 return typeof(void); 109 return typeof(void);
102 } 110 }
103 } 111 }
104 112
105 public IPromise Then(Action success, Action<Exception> error, Action cancel) { 113 public IPromise Then(Action success, Action<Exception> error, Action<Exception> cancel) {
106 var promise = new Promise(); 114 var promise = new Promise();
107 if (success != null) 115 if (success != null)
108 promise.On(Cancel, PromiseEventType.Cancelled); 116 promise.On(Cancel, PromiseEventType.Cancelled);
109 117
110 AddHandler(new HandlerDescriptor(success, error, cancel, promise)); 118 AddHandler(new HandlerDescriptor(success, error, cancel, promise));
118 126
119 public IPromise Then(Action success) { 127 public IPromise Then(Action success) {
120 return Then(success, null, null); 128 return Then(success, null, null);
121 } 129 }
122 130
123 public IPromise On(Action success, Action<Exception> error, Action cancel) { 131 public IPromise On(Action success, Action<Exception> error, Action<Exception> cancel) {
124 AddHandler(new HandlerDescriptor(success, error, cancel, null)); 132 AddHandler(new HandlerDescriptor(success, error, cancel, null));
125 return this; 133 return this;
126 } 134 }
127 135
128 public IPromise On(Action success, Action<Exception> error) { 136 public IPromise On(Action success, Action<Exception> error) {
135 143
136 public IPromise On(Action handler, PromiseEventType events) { 144 public IPromise On(Action handler, PromiseEventType events) {
137 return On( 145 return On(
138 events.HasFlag(PromiseEventType.Success) ? handler : null, 146 events.HasFlag(PromiseEventType.Success) ? handler : null,
139 events.HasFlag(PromiseEventType.Error) ? new Action<Exception>(err => handler()) : null, 147 events.HasFlag(PromiseEventType.Error) ? new Action<Exception>(err => handler()) : null,
140 events.HasFlag(PromiseEventType.Cancelled) ? handler : null 148 events.HasFlag(PromiseEventType.Cancelled) ? new Action<Exception>(reason => handler()) : null
141 ); 149 );
142 } 150 }
143 151
144 public IPromise<T> Cast<T>() { 152 public IPromise<T> Cast<T>() {
145 throw new InvalidCastException(); 153 throw new InvalidCastException();
146 } 154 }
147 155
148 public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<IPromise> cancel) { 156 public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<Exception,IPromise> cancel) {
149 var medium = new Promise(); 157 var medium = new Promise();
150 158
151 On( 159 On(
152 () => { 160 () => {
153 if (medium.IsCancelled) 161 if (medium.IsCancelled)
166 } 174 }
167 } else { 175 } else {
168 medium.Reject(ex); 176 medium.Reject(ex);
169 } 177 }
170 }, 178 },
171 () => { 179 reason => {
172 if (medium.IsCancelled) 180 if (medium.IsCancelled)
173 return; 181 return;
174 if (cancel != null) 182 if (cancel != null)
175 ConnectPromise(cancel(), medium); 183 ConnectPromise(cancel(reason), medium);
176 else 184 else
177 medium.Cancel(); 185 medium.Cancel(reason);
178 } 186 }
179 ); 187 );
180 188
181 if (chained != null) 189 if (chained != null)
182 medium.On(Cancel, PromiseEventType.Cancelled); 190 medium.On(Cancel, PromiseEventType.Cancelled);
187 static void ConnectPromise(IPromise result, Promise medium) { 195 static void ConnectPromise(IPromise result, Promise medium) {
188 if (result != null) { 196 if (result != null) {
189 result.On( 197 result.On(
190 medium.Resolve, 198 medium.Resolve,
191 medium.Reject, 199 medium.Reject,
192 () => medium.Reject(new OperationCanceledException()) 200 medium.Cancel
193 ); 201 );
194 medium.On(result.Cancel, PromiseEventType.Cancelled); 202 medium.On(null,null,result.Cancel);
195 } else { 203 } else {
196 medium.Reject( 204 medium.Reject(
197 new NullReferenceException( 205 new NullReferenceException(
198 "The chained asynchronous operation returned" + 206 "The chained asynchronous operation returned" +
199 " 'null' where the promise instance is expected" 207 " 'null' where the promise instance is expected"
207 } 215 }
208 216
209 public IPromise Chain(Func<IPromise> chained) { 217 public IPromise Chain(Func<IPromise> chained) {
210 return Chain(chained, null, null); 218 return Chain(chained, null, null);
211 } 219 }
212
213 public IPromise Error(Action<Exception> error) {
214 var promise = new Promise();
215 On(
216 null,
217 err => {
218 if (error != null)
219 try {
220 error(err);
221 promise.Resolve();
222 } catch (Exception err2) {
223 promise.Reject(err2);
224 }
225 else
226 promise.Reject(err);
227 }
228 );
229
230 return promise;
231 }
232
233 public IPromise Cancelled(Action handler) {
234 var promise = new Promise();
235 On(
236 null,
237 null,
238 () => {
239 if (handler != null) {
240 try {
241 handler();
242 promise.Resolve();
243 } catch (Exception err) {
244 promise.Reject(err);
245 }
246 } else {
247 promise.Cancel();
248 }
249 }
250 );
251
252 return promise;
253 }
254
255
256 } 220 }
257 } 221 }
258 222