Mercurial > pub > ImplabNet
comparison Implab/AbstractEvent.cs @ 244:eee3e49dd1ff v3
working on promises
| author | cin |
|---|---|
| date | Thu, 25 Jan 2018 19:09:16 +0300 |
| parents | b1e0ffdf3451 |
| children | 5cb4826c2c2a |
comparison
equal
deleted
inserted
replaced
| 243:b1e0ffdf3451 | 244:eee3e49dd1ff |
|---|---|
| 33 /// </description> | 33 /// </description> |
| 34 /// </list> | 34 /// </list> |
| 35 /// </para> | 35 /// </para> |
| 36 /// </remarks> | 36 /// </remarks> |
| 37 public abstract class AbstractEvent<THandler> where THandler : class { | 37 public abstract class AbstractEvent<THandler> where THandler : class { |
| 38 const int PENDING_SATE = 0; | 38 const int PendingState = 0; |
| 39 | 39 |
| 40 const int TRANSITIONAL_STATE = 1; | 40 const int TransitionalState = 1; |
| 41 | 41 |
| 42 const int FULFILLED_STATE = 2; | 42 const int ResolvedState = 2; |
| 43 | 43 |
| 44 volatile int m_state; | 44 volatile int m_state; |
| 45 | 45 |
| 46 THandler m_handler; | 46 THandler m_handler; |
| 47 SimpleAsyncQueue<THandler> m_extraHandlers; | 47 SimpleAsyncQueue<THandler> m_extraHandlers; |
| 48 | 48 |
| 49 public bool IsFulfilled { | 49 public bool IsResolved { |
| 50 get { | 50 get { |
| 51 return m_state > TRANSITIONAL_STATE; | 51 return m_state > TransitionalState; |
| 52 } | 52 } |
| 53 } | 53 } |
| 54 | 54 |
| 55 #region state managment | 55 #region state managment |
| 56 protected bool BeginTransit() { | 56 protected bool BeginTransit() { |
| 57 return PENDING_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, PENDING_SATE); | 57 return PendingState == Interlocked.CompareExchange(ref m_state, TransitionalState, PendingState); |
| 58 } | 58 } |
| 59 | 59 |
| 60 protected void CompleteTransit() { | 60 protected void CompleteTransit() { |
| 61 #if DEBUG | 61 #if DEBUG |
| 62 if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, FULFILLED_STATE, TRANSITIONAL_STATE)) | 62 if (TransitionalState != Interlocked.CompareExchange(ref m_state, ResolvedState, TransitionalState)) |
| 63 throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state"); | 63 throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state"); |
| 64 #else | 64 #else |
| 65 m_state = state; | 65 m_state = state; |
| 66 #endif | 66 #endif |
| 67 Signal(); | 67 Signal(); |
| 68 } | 68 } |
| 69 | 69 |
| 70 protected void WaitTransition() { | 70 protected void WaitTransition() { |
| 71 if (m_state == TRANSITIONAL_STATE) { | 71 if (m_state == TransitionalState) { |
| 72 SpinWait spin; | 72 SpinWait spin; |
| 73 do { | 73 do { |
| 74 spin.SpinOnce(); | 74 spin.SpinOnce(); |
| 75 } while (m_state == TRANSITIONAL_STATE); | 75 } while (m_state == TransitionalState); |
| 76 } | 76 } |
| 77 } | 77 } |
| 78 | 78 |
| 79 | 79 |
| 80 protected abstract void SignalHandler(THandler handler); | 80 protected abstract void SignalHandler(THandler handler); |
| 89 | 89 |
| 90 protected abstract Signal GetFulfillSignal(); | 90 protected abstract Signal GetFulfillSignal(); |
| 91 | 91 |
| 92 #region synchronization traits | 92 #region synchronization traits |
| 93 protected void WaitResult(int timeout) { | 93 protected void WaitResult(int timeout) { |
| 94 if (!(IsFulfilled || GetFulfillSignal().Wait(timeout))) | 94 if (!(IsResolved || GetFulfillSignal().Wait(timeout))) |
| 95 throw new TimeoutException(); | 95 throw new TimeoutException(); |
| 96 } | 96 } |
| 97 | 97 |
| 98 | 98 |
| 99 #endregion | 99 #endregion |
| 100 | 100 |
| 101 #region handlers managment | 101 #region handlers managment |
| 102 | 102 |
| 103 protected void AddHandler(THandler handler) { | 103 protected void AddHandler(THandler handler) { |
| 104 | 104 |
| 105 if (IsFulfilled) { | 105 if (IsResolved) { |
| 106 // the promise is in the resolved state, just invoke the handler | 106 // the promise is in the resolved state, just invoke the handler |
| 107 SignalHandler(handler); | 107 SignalHandler(handler); |
| 108 } else { | 108 } else { |
| 109 EnqueueHandler(handler); | 109 EnqueueHandler(handler); |
| 110 | 110 |
| 111 if (IsFulfilled && TryDequeueHandler(out handler)) | 111 if (IsResolved && TryDequeueHandler(out handler)) |
| 112 // if the promise have been resolved while we was adding the handler to the queue | 112 // if the promise have been resolved while we was adding the handler to the queue |
| 113 // we can't guarantee that someone is still processing it | 113 // we can't guarantee that someone is still processing it |
| 114 // therefore we need to fetch a handler from the queue and execute it | 114 // therefore we need to fetch a handler from the queue and execute it |
| 115 // note that fetched handler may be not the one that we have added | 115 // note that fetched handler may be not the one that we have added |
| 116 // even we can fetch no handlers at all :) | 116 // even we can fetch no handlers at all :) |
