Mercurial > pub > ImplabNet
comparison Implab/CancellationToken.cs @ 248:5cb4826c2c2a v3
Added awaiters to promises
Added static methods to Promise Resolve, Reject, All.
Updated promise helpers
author | cin |
---|---|
date | Tue, 30 Jan 2018 01:37:17 +0300 |
parents | fa6cbf4d8841 |
children |
comparison
equal
deleted
inserted
replaced
247:fb70574741a1 | 248:5cb4826c2c2a |
---|---|
1 using System; | 1 using System; |
2 using System.Threading; | 2 using System.Threading; |
3 using Implab.Parallels; | 3 using Implab.Parallels; |
4 | 4 |
5 namespace Implab { | 5 namespace Implab { |
6 public class CancellationToken : ICancellationToken { | 6 /// <summary> |
7 const int CANCEL_NOT_REQUESTED = 0; | 7 /// The cancellation token signals to the worker that cancellation has been |
8 const int CANCEL_REQUESTING = 1; | 8 /// requested, after the signal is received the worker decides wheather to |
9 const int CANCEL_REQUESTED = 2; | 9 /// cancel its work or to continue. |
10 /// </summary> | |
11 public class CancellationToken : AbstractEvent<Action<Exception>> { | |
12 public CancellationToken() { | |
13 | |
14 } | |
15 | |
16 public void RequestCancellation() { | |
10 | 17 |
11 volatile int m_state = CANCEL_NOT_REQUESTED; | |
12 | |
13 Action<Exception> m_handler; | |
14 | |
15 Parallels.SimpleAsyncQueue<Action<Exception>> m_handlers; | |
16 | |
17 public bool IsCancellationRequested { | |
18 get { return m_state == CANCEL_REQUESTED; } | |
19 } | 18 } |
20 | 19 |
21 public Exception CancellationReason { | 20 public void RequestCancellation(Exception reason) { |
22 get; set; | |
23 } | |
24 | 21 |
25 public void CancellationRequested(Action<Exception> handler) { | |
26 Safe.ArgumentNotNull(handler, nameof(handler)); | |
27 if (IsCancellationRequested) { | |
28 handler(CancellationReason); | |
29 } else { | |
30 EnqueueHandler(handler); | |
31 if (IsCancellationRequested && TryDequeueHandler(out handler)) | |
32 handler(CancellationReason); | |
33 } | |
34 } | |
35 | |
36 bool TryDequeueHandler(out Action<Exception> handler) { | |
37 handler = Interlocked.Exchange(ref m_handler, null); | |
38 if (handler != null) | |
39 return true; | |
40 else if (m_handlers != null) | |
41 return m_handlers.TryDequeue(out handler); | |
42 else | |
43 return false; | |
44 } | |
45 | |
46 void EnqueueHandler(Action<Exception> handler) { | |
47 if (Interlocked.CompareExchange(ref m_handler, handler, null) != null) { | |
48 if (m_handlers == null) | |
49 // compare-exchange will fprotect from loosing already created queue | |
50 Interlocked.CompareExchange(ref m_handlers, new SimpleAsyncQueue<Action<Exception>>(), null); | |
51 m_handlers.Enqueue(handler); | |
52 } | |
53 } | |
54 | |
55 void RequestCancellation(Exception reason) { | |
56 if (Interlocked.CompareExchange(ref m_state, CANCEL_REQUESTING, CANCEL_NOT_REQUESTED) == CANCEL_NOT_REQUESTED) { | |
57 if (reason == null) | |
58 reason = new OperationCanceledException(); | |
59 CancellationReason = reason; | |
60 m_state = CANCEL_REQUESTED; | |
61 } | |
62 } | 22 } |
63 | 23 |
24 protected override void SignalHandler(Action<Exception> handler) { | |
25 throw new NotImplementedException(); | |
26 } | |
64 } | 27 } |
65 } | 28 } |