##// END OF EJS Templates
refactoring
cin -
r11:6ec82bf68c8e promises
parent child
Show More
1 NO CONTENT: new file 100644, binary diff hidden
@@ -0,0 +1,28
1 using System;
2 using System.Threading;
3
4 namespace Implab.Parallels {
5 /// <summary>
6 /// Класс для распаралеливания задач.
7 /// </summary>
8 /// <remarks>
9 /// Используя данный класс и лямда выражения можно распараллелить
10 /// вычисления, для этого используется концепция обещаний.
11 /// </remarks>
12 public static class AsyncPool {
13
14 public static Promise<T> Invoke<T>(Func<T> func) {
15 var p = new Promise<T>();
16
17 ThreadPool.QueueUserWorkItem(param => {
18 try {
19 p.Resolve(func());
20 } catch(Exception e) {
21 p.Reject(e);
22 }
23 });
24
25 return p;
26 }
27 }
28 }
@@ -2,6 +2,7 using System;
2 2 using Microsoft.VisualStudio.TestTools.UnitTesting;
3 3 using System.Reflection;
4 4 using System.Threading;
5 using Implab.Parallels;
5 6
6 7 namespace Implab.Test
7 8 {
@@ -70,6 +71,17 namespace Implab.Test
70 71 }
71 72
72 73 [TestMethod]
74 public void FixErrorTest() {
75 var p = new Promise<int>();
76
77 var p2 = p.Error(e => 101);
78
79 p.Reject(new Exception());
80
81 Assert.AreEqual(p2.Join(), 101);
82 }
83
84 [TestMethod]
73 85 public void ChainTest ()
74 86 {
75 87 var p1 = new Promise<int> ();
@@ -1,4 +1,5
1 using System;
1 using Implab.Parallels;
2 using System;
2 3 using System.Collections.Generic;
3 4 using System.Linq;
4 5 using System.Text;
@@ -24,11 +24,10 namespace Implab
24 24 }
25 25
26 26 /// <summary>
27 /// Tries to cancel the promise or the complete chain.
27 /// Tries to cancel the the complete chain of promises.
28 28 /// </summary>
29 /// <param name="dependencies">Try to cancel the whole promise chain, the parent promise will be cancelled only if it has only one promise</param>
30 /// <returns></returns>
31 bool Cancel(bool dependencies);
29 /// <returns><c>true</c> - if the promise has been cancelled, otherwise the promise will be resolved (or resolved already).</returns>
30 bool Cancel();
32 31
33 32 /// <summary>
34 33 /// Registers handler for the case when the promise is cencelled. If the promise already cancelled the
@@ -38,12 +38,10
38 38 <Compile Include="ProgressInitEventArgs.cs" />
39 39 <Compile Include="Properties\AssemblyInfo.cs" />
40 40 <Compile Include="Promise.cs" />
41 <Compile Include="AsyncPool.cs" />
41 <Compile Include="Parallels\AsyncPool.cs" />
42 42 <Compile Include="Safe.cs" />
43 43 <Compile Include="ValueEventArgs.cs" />
44 44 </ItemGroup>
45 45 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
46 <ItemGroup>
47 <Folder Include="Parallels\" />
48 </ItemGroup>
46 <ItemGroup />
49 47 </Project> No newline at end of file
@@ -7,7 +7,7 using System.Threading;
7 7 namespace Implab {
8 8
9 9 public delegate void ErrorHandler(Exception e);
10
10 public delegate T ErrorHandler<out T>(Exception e);
11 11 public delegate void ResultHandler<in T>(T result);
12 12 public delegate TNew ResultMapper<in TSrc, out TNew>(TSrc result);
13 13 public delegate Promise<TNew> ChainedOperation<in TSrc, TNew>(TSrc result);
@@ -126,52 +126,18 namespace Implab {
126 126 return Cancel(true);
127 127 }
128 128
129 protected virtual void OnStateChanged() {
130 switch (m_state) {
131 case PromiseState.Resolved:
132 foreach (var resultHandlerInfo in m_resultHandlers)
133 try {
134 if (resultHandlerInfo.resultHandler != null)
135 resultHandlerInfo.resultHandler(m_result);
136 } catch (Exception e) {
137 try {
138 if (resultHandlerInfo.errorHandler != null)
139 resultHandlerInfo.errorHandler(e);
140 } catch { }
141 }
142 break;
143 case PromiseState.Cancelled:
144 foreach (var cancelHandler in m_cancelHandlers)
145 cancelHandler();
146 break;
147 case PromiseState.Rejected:
148 foreach (var resultHandlerInfo in m_resultHandlers)
149 try {
150 if (resultHandlerInfo.errorHandler != null)
151 resultHandlerInfo.errorHandler(m_error);
152 } catch { }
153 break;
154 default:
155 throw new InvalidOperationException(String.Format("Promise entered an invalid state {0}", m_state));
156 }
157
158 m_resultHandlers = null;
159 m_cancelHandlers = null;
160 }
161
162 129 /// <summary>
163 /// Добавляет обработчики событий выполнения обещания.
130 /// Adds new handlers to this promise.
164 131 /// </summary>
165 /// <param name="success">Обработчик успешного выполнения обещания.
166 /// Данному обработчику будет передан результат выполнения операции.</param>
167 /// <param name="error">Обработчик ошибки. Данный обработчик получит
168 /// исключение возникшее при выполнении операции.</param>
169 /// <returns>Само обещание</returns>
132 /// <param name="success">The handler of the successfully completed operation.
133 /// This handler will recieve an operation result as a parameter.</param>
134 /// <param name="error">Handles an exception that may occur during the operation.</param>
135 /// <returns>The new promise chained to this one.</returns>
170 136 public Promise<T> Then(ResultHandler<T> success, ErrorHandler error) {
171 137 if (success == null && error == null)
172 138 return this;
173 139
174 var medium = new Promise<T>();
140 var medium = new Promise<T>(this, true);
175 141
176 142 var handlerInfo = new ResultHandlerInfo();
177 143
@@ -198,14 +164,99 namespace Implab {
198 164 return medium;
199 165 }
200 166
167 /// <summary>
168 /// Adds new handlers to this promise.
169 /// </summary>
170 /// <param name="success">The handler of the successfully completed operation.
171 /// This handler will recieve an operation result as a parameter.</param>
172 /// <param name="error">Handles an exception that may occur during the operation and returns the value which will be used as the result of the operation.</param>
173 /// <returns>The new promise chained to this one.</returns>
174 public Promise<T> Then(ResultHandler<T> success, ErrorHandler<T> error) {
175 if (success == null && error == null)
176 return this;
177
178 var medium = new Promise<T>(this, true);
179
180 var handlerInfo = new ResultHandlerInfo();
181
182 if (success != null)
183 handlerInfo.resultHandler = x => {
184 success(x);
185 medium.Resolve(x);
186 };
187 else
188 handlerInfo.resultHandler = medium.Resolve;
189
190 if (error != null)
191 handlerInfo.errorHandler = x => {
192 try {
193 medium.Resolve(error(x));
194 } catch { }
195 medium.Reject(x);
196 };
197 else
198 handlerInfo.errorHandler = medium.Reject;
199
200 AddHandler(handlerInfo);
201
202 return medium;
203 }
204
205
201 206 public Promise<T> Then(ResultHandler<T> success) {
202 return Then(success, null);
207 if (success == null)
208 return this;
209
210 var medium = new Promise<T>(this, true);
211
212 var handlerInfo = new ResultHandlerInfo();
213
214 if (success != null)
215 handlerInfo.resultHandler = x => {
216 success(x);
217 medium.Resolve(x);
218 };
219 else
220 handlerInfo.resultHandler = medium.Resolve;
221
222 handlerInfo.errorHandler = medium.Reject;
223
224 AddHandler(handlerInfo);
225
226 return medium;
203 227 }
204 228
205 229 public Promise<T> Error(ErrorHandler error) {
206 230 return Then(null, error);
207 231 }
208 232
233 /// <summary>
234 /// Handles error and allows to keep the promise.
235 /// </summary>
236 /// <remarks>
237 /// If the specified handler throws an exception, this exception will be used to reject the promise.
238 /// </remarks>
239 /// <param name="handler">The error handler which returns the result of the promise.</param>
240 /// <returns>New promise.</returns>
241 public Promise<T> Error(ErrorHandler<T> handler) {
242 if (handler == null)
243 return this;
244
245 var medium = new Promise<T>(this, true);
246
247 AddHandler(new ResultHandlerInfo {
248 errorHandler = e => {
249 try {
250 medium.Resolve(handler(e));
251 } catch (Exception e2) {
252 medium.Reject(e2);
253 }
254 }
255 });
256
257 return medium;
258 }
259
209 260 public Promise<T> Anyway(Action handler) {
210 261 if (handler == null)
211 262 return this;
@@ -295,9 +346,9 namespace Implab {
295 346 // notify chained operation that it's not needed
296 347 medium.Cancelled(() => promise.Cancel());
297 348 promise.Then(
298 medium.Resolve,
299 medium.Reject
300 );
349 x => medium.Resolve(x),
350 e => medium.Reject(e)
351 );
301 352 },
302 353 errorHandler = delegate(Exception e) {
303 354 if (error != null)
@@ -416,6 +467,39 namespace Implab {
416 467 }
417 468 }
418 469
470 protected virtual void OnStateChanged() {
471 switch (m_state) {
472 case PromiseState.Resolved:
473 foreach (var resultHandlerInfo in m_resultHandlers)
474 try {
475 if (resultHandlerInfo.resultHandler != null)
476 resultHandlerInfo.resultHandler(m_result);
477 } catch (Exception e) {
478 try {
479 if (resultHandlerInfo.errorHandler != null)
480 resultHandlerInfo.errorHandler(e);
481 } catch { }
482 }
483 break;
484 case PromiseState.Cancelled:
485 foreach (var cancelHandler in m_cancelHandlers)
486 cancelHandler();
487 break;
488 case PromiseState.Rejected:
489 foreach (var resultHandlerInfo in m_resultHandlers)
490 try {
491 if (resultHandlerInfo.errorHandler != null)
492 resultHandlerInfo.errorHandler(m_error);
493 } catch { }
494 break;
495 default:
496 throw new InvalidOperationException(String.Format("Promise entered an invalid state {0}", m_state));
497 }
498
499 m_resultHandlers = null;
500 m_cancelHandlers = null;
501 }
502
419 503
420 504
421 505 public bool IsExclusive {
@@ -434,7 +518,7 namespace Implab {
434 518 }
435 519 }
436 520
437 public bool Cancel(bool dependencies) {
521 protected bool Cancel(bool dependencies) {
438 522 bool result;
439 523
440 524 lock (m_lock) {
@@ -450,7 +534,7 namespace Implab {
450 534 OnStateChanged();
451 535
452 536 if (dependencies && m_parent != null && m_parent.IsExclusive) {
453 m_parent.Cancel(true);
537 m_parent.Cancel();
454 538 }
455 539
456 540 return result;
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now