Mercurial > pub > ImplabNet
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 |