Mercurial > pub > ImplabNet
comparison Implab/FuncChainTaskBase.cs @ 187:dd4a3590f9c6 ref20160224
Reworked cancelation handling, if the cancel handler isn't specified the OperationCanceledException will be handled by the error handler
Any unhandled OperationCanceledException will cause the promise cancelation
author | cin |
---|---|
date | Tue, 19 Apr 2016 17:35:20 +0300 |
parents | eb793fbbe4ea |
children | 40d7fed4a09e |
comparison
equal
deleted
inserted
replaced
186:75103928da09 | 187:dd4a3590f9c6 |
---|---|
1 using System; | 1 using System; |
2 using System.Threading; | |
3 | 2 |
4 namespace Implab { | 3 namespace Implab { |
5 public class FuncChainTaskBase<TResult> : AbstractPromise<TResult> { | 4 public class FuncChainTaskBase<TResult> : AbstractTask<TResult> { |
6 readonly Func<Exception, IPromise<TResult>> m_error; | 5 readonly Func<Exception, IPromise<TResult>> m_error; |
7 readonly Func<Exception, IPromise<TResult>> m_cancel; | 6 readonly Func<Exception, IPromise<TResult>> m_cancel; |
8 | |
9 int m_cancelationLock; | |
10 | 7 |
11 protected FuncChainTaskBase( Func<Exception, IPromise<TResult>> error, Func<Exception, IPromise<TResult>> cancel, bool autoCancellable) { | 8 protected FuncChainTaskBase( Func<Exception, IPromise<TResult>> error, Func<Exception, IPromise<TResult>> cancel, bool autoCancellable) { |
12 m_error = error; | 9 m_error = error; |
13 m_cancel = cancel; | 10 m_cancel = cancel; |
14 if (autoCancellable) | 11 if (autoCancellable) |
19 if (LockCancelation()) | 16 if (LockCancelation()) |
20 HandleErrorInternal(error); | 17 HandleErrorInternal(error); |
21 } | 18 } |
22 | 19 |
23 public override void CancelOperation(Exception reason) { | 20 public override void CancelOperation(Exception reason) { |
24 if (LockCancelation()) { | 21 if (LockCancelation()) |
25 if (m_cancel != null) { | 22 HandleCancelInternal(reason); |
26 try { | |
27 m_cancel(reason).On(SetResult, HandleErrorInternal, SetCancelled); | |
28 } catch (Exception err) { | |
29 HandleErrorInternal(err); | |
30 } | |
31 } else { | |
32 SetCancelled(reason); | |
33 } | |
34 } | |
35 | |
36 } | 23 } |
37 | 24 |
38 protected void HandleErrorInternal(Exception error) { | 25 protected void HandleErrorInternal(Exception error) { |
39 if (m_error != null) { | 26 if (m_error != null) { |
40 try { | 27 try { |
41 var operation = m_error(error); | 28 var p = m_error(error); |
42 | 29 p.On(SetResult, SetErrorInternal, SetCancelledInternal); |
43 operation.On(SetResult, SetError, SetCancelled); | 30 CancellationRequested(p.Cancel); |
44 CancellationRequested(operation.Cancel); | |
45 } catch(Exception err) { | 31 } catch(Exception err) { |
46 SetError(err); | 32 SetErrorInternal(err); |
47 } | 33 } |
48 } else { | 34 } else { |
49 SetError(error); | 35 SetErrorInternal(error); |
50 } | 36 } |
51 } | 37 } |
52 | 38 |
53 protected bool LockCancelation() { | 39 protected void HandleCancelInternal(Exception reason) { |
54 return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0); | 40 if (m_cancel != null) { |
41 try { | |
42 var p = m_cancel(reason); | |
43 p.On(SetResult, HandleErrorInternal, SetCancelledInternal); | |
44 CancellationRequested(p.Cancel); | |
45 } catch (Exception err) { | |
46 HandleErrorInternal(err); | |
47 } | |
48 } else { | |
49 HandleErrorInternal(reason ?? new OperationCanceledException()); | |
50 } | |
55 } | 51 } |
56 } | 52 } |
57 } | 53 } |
58 | 54 |