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 }