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