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 :) |