Mercurial > pub > ImplabNet
comparison Implab/CancellationToken.cs @ 240:fa6cbf4d8841 v3
refactoring, moving to dotnercore, simplifying promises
| author | cin |
|---|---|
| date | Tue, 23 Jan 2018 19:39:21 +0300 |
| parents | |
| children | 5cb4826c2c2a |
comparison
equal
deleted
inserted
replaced
| 239:eedf4d834e67 | 240:fa6cbf4d8841 |
|---|---|
| 1 using System; | |
| 2 using System.Threading; | |
| 3 using Implab.Parallels; | |
| 4 | |
| 5 namespace Implab { | |
| 6 public class CancellationToken : ICancellationToken { | |
| 7 const int CANCEL_NOT_REQUESTED = 0; | |
| 8 const int CANCEL_REQUESTING = 1; | |
| 9 const int CANCEL_REQUESTED = 2; | |
| 10 | |
| 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 } | |
| 20 | |
| 21 public Exception CancellationReason { | |
| 22 get; set; | |
| 23 } | |
| 24 | |
| 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 } | |
| 63 | |
| 64 } | |
| 65 } |
