annotate Implab/CancellationToken.cs @ 243:b1e0ffdf3451 v3

working on promises
author cin
date Wed, 24 Jan 2018 19:24:10 +0300
parents fa6cbf4d8841
children 5cb4826c2c2a
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
240
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
1 using System;
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
2 using System.Threading;
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
3 using Implab.Parallels;
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
4
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
5 namespace Implab {
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
6 public class CancellationToken : ICancellationToken {
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
7 const int CANCEL_NOT_REQUESTED = 0;
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
8 const int CANCEL_REQUESTING = 1;
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
9 const int CANCEL_REQUESTED = 2;
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
10
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
11 volatile int m_state = CANCEL_NOT_REQUESTED;
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
12
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
13 Action<Exception> m_handler;
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
14
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
15 Parallels.SimpleAsyncQueue<Action<Exception>> m_handlers;
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
16
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
17 public bool IsCancellationRequested {
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
18 get { return m_state == CANCEL_REQUESTED; }
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
19 }
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
20
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
21 public Exception CancellationReason {
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
22 get; set;
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
23 }
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
24
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
25 public void CancellationRequested(Action<Exception> handler) {
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
26 Safe.ArgumentNotNull(handler, nameof(handler));
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
27 if (IsCancellationRequested) {
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
28 handler(CancellationReason);
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
29 } else {
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
30 EnqueueHandler(handler);
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
31 if (IsCancellationRequested && TryDequeueHandler(out handler))
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
32 handler(CancellationReason);
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
33 }
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
34 }
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
35
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
36 bool TryDequeueHandler(out Action<Exception> handler) {
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
37 handler = Interlocked.Exchange(ref m_handler, null);
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
38 if (handler != null)
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
39 return true;
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
40 else if (m_handlers != null)
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
41 return m_handlers.TryDequeue(out handler);
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
42 else
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
43 return false;
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
44 }
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
45
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
46 void EnqueueHandler(Action<Exception> handler) {
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
47 if (Interlocked.CompareExchange(ref m_handler, handler, null) != null) {
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
48 if (m_handlers == null)
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
49 // compare-exchange will fprotect from loosing already created queue
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
50 Interlocked.CompareExchange(ref m_handlers, new SimpleAsyncQueue<Action<Exception>>(), null);
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
51 m_handlers.Enqueue(handler);
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
52 }
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
53 }
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
54
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
55 void RequestCancellation(Exception reason) {
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
56 if (Interlocked.CompareExchange(ref m_state, CANCEL_REQUESTING, CANCEL_NOT_REQUESTED) == CANCEL_NOT_REQUESTED) {
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
57 if (reason == null)
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
58 reason = new OperationCanceledException();
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
59 CancellationReason = reason;
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
60 m_state = CANCEL_REQUESTED;
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
61 }
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
62 }
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
63
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
64 }
fa6cbf4d8841 refactoring, moving to dotnercore, simplifying promises
cin
parents:
diff changeset
65 }