Mercurial > pub > ImplabNet
comparison Implab/AbstractPromise.cs @ 125:f803565868a4 v2
improved performance of promises
| author | cin |
|---|---|
| date | Thu, 15 Jan 2015 12:09:20 +0300 |
| parents | 2573b562e328 |
| children | 671f60cd0250 |
comparison
equal
deleted
inserted
replaced
| 124:a336cb13c6a9 | 125:f803565868a4 |
|---|---|
| 10 const int TRANSITIONAL_STATE = 1; | 10 const int TRANSITIONAL_STATE = 1; |
| 11 const int SUCCEEDED_STATE = 2; | 11 const int SUCCEEDED_STATE = 2; |
| 12 const int REJECTED_STATE = 3; | 12 const int REJECTED_STATE = 3; |
| 13 const int CANCELLED_STATE = 4; | 13 const int CANCELLED_STATE = 4; |
| 14 | 14 |
| 15 const int RESERVED_HANDLERS_COUNT = 4; | |
| 16 | |
| 15 int m_state; | 17 int m_state; |
| 16 Exception m_error; | 18 Exception m_error; |
| 17 | 19 int m_handlersCount; |
| 18 readonly AsyncQueue<THandler> m_handlers = new AsyncQueue<THandler>(); | 20 |
| 21 readonly THandler[] m_handlers = new THandler[RESERVED_HANDLERS_COUNT]; | |
| 22 MTQueue<THandler> m_extraHandlers; | |
| 23 int m_handlerPointer = -1; | |
| 24 int m_handlersCommited; | |
| 19 | 25 |
| 20 #region state managment | 26 #region state managment |
| 21 bool BeginTransit() { | 27 bool BeginTransit() { |
| 22 return UNRESOLVED_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, UNRESOLVED_SATE); | 28 return UNRESOLVED_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, UNRESOLVED_SATE); |
| 23 } | 29 } |
| 86 protected abstract void SignalError(THandler handler, Exception error); | 92 protected abstract void SignalError(THandler handler, Exception error); |
| 87 | 93 |
| 88 protected abstract void SignalCancelled(THandler handler); | 94 protected abstract void SignalCancelled(THandler handler); |
| 89 | 95 |
| 90 void OnSuccess() { | 96 void OnSuccess() { |
| 91 THandler handler; | 97 var hp = m_handlerPointer; |
| 92 while (m_handlers.TryDequeue(out handler)) | 98 var slot = hp +1 ; |
| 93 SignalSuccess(handler); | 99 while (slot < m_handlersCommited) { |
| 100 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) { | |
| 101 SignalSuccess(m_handlers[slot]); | |
| 102 } | |
| 103 hp = m_handlerPointer; | |
| 104 slot = hp +1 ; | |
| 105 } | |
| 106 | |
| 107 | |
| 108 if (m_extraHandlers != null) { | |
| 109 THandler handler; | |
| 110 while (m_extraHandlers.TryDequeue(out handler)) | |
| 111 SignalSuccess(handler); | |
| 112 } | |
| 94 } | 113 } |
| 95 | 114 |
| 96 void OnError() { | 115 void OnError() { |
| 97 THandler handler; | 116 var hp = m_handlerPointer; |
| 98 while (m_handlers.TryDequeue(out handler)) | 117 var slot = hp +1 ; |
| 99 SignalError(handler,m_error); | 118 while (slot < m_handlersCommited) { |
| 119 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) { | |
| 120 SignalError(m_handlers[slot],m_error); | |
| 121 } | |
| 122 hp = m_handlerPointer; | |
| 123 slot = hp +1 ; | |
| 124 } | |
| 125 | |
| 126 if (m_extraHandlers != null) { | |
| 127 THandler handler; | |
| 128 while (m_extraHandlers.TryDequeue(out handler)) | |
| 129 SignalError(handler, m_error); | |
| 130 } | |
| 100 } | 131 } |
| 101 | 132 |
| 102 void OnCancelled() { | 133 void OnCancelled() { |
| 103 THandler handler; | 134 var hp = m_handlerPointer; |
| 104 while (m_handlers.TryDequeue(out handler)) | 135 var slot = hp +1 ; |
| 105 SignalCancelled(handler); | 136 while (slot < m_handlersCommited) { |
| 137 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) { | |
| 138 SignalCancelled(m_handlers[slot]); | |
| 139 } | |
| 140 hp = m_handlerPointer; | |
| 141 slot = hp +1 ; | |
| 142 } | |
| 143 | |
| 144 if (m_extraHandlers != null) { | |
| 145 THandler handler; | |
| 146 while (m_extraHandlers.TryDequeue(out handler)) | |
| 147 SignalCancelled(handler); | |
| 148 } | |
| 106 } | 149 } |
| 107 | 150 |
| 108 #endregion | 151 #endregion |
| 109 | 152 |
| 110 protected abstract void Listen(PromiseEventType events, Action handler); | 153 protected abstract void Listen(PromiseEventType events, Action handler); |
| 143 | 186 |
| 144 #region handlers managment | 187 #region handlers managment |
| 145 | 188 |
| 146 protected void AddHandler(THandler handler) { | 189 protected void AddHandler(THandler handler) { |
| 147 | 190 |
| 148 if (IsResolved) { | 191 if (m_state > 1) { |
| 192 // the promise is in the resolved state, just invoke the handler | |
| 149 InvokeHandler(handler); | 193 InvokeHandler(handler); |
| 150 | |
| 151 } else { | 194 } else { |
| 152 // the promise is in the resolved state, just invoke the handler | 195 var slot = Interlocked.Increment(ref m_handlersCount) - 1; |
| 153 m_handlers.Enqueue(handler); | 196 |
| 154 | 197 if (slot < RESERVED_HANDLERS_COUNT) { |
| 155 | 198 m_handlers[slot] = handler; |
| 156 if (IsResolved && m_handlers.TryDequeue(out handler)) | 199 |
| 200 while (slot != Interlocked.CompareExchange(ref m_handlersCommited, slot + 1, slot)) { | |
| 201 } | |
| 202 | |
| 203 if (m_state > 1) { | |
| 204 do { | |
| 205 var hp = m_handlerPointer; | |
| 206 slot = hp + 1; | |
| 207 if (slot < m_handlersCommited) { | |
| 208 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) != hp) | |
| 209 continue; | |
| 210 InvokeHandler(m_handlers[slot]); | |
| 211 } | |
| 212 break; | |
| 213 } while(true); | |
| 214 } | |
| 215 } else { | |
| 216 if (slot == RESERVED_HANDLERS_COUNT) { | |
| 217 m_extraHandlers = new MTQueue<THandler>(); | |
| 218 } else { | |
| 219 while (m_extraHandlers == null) | |
| 220 Thread.MemoryBarrier(); | |
| 221 } | |
| 222 | |
| 223 m_extraHandlers.Enqueue(handler); | |
| 224 | |
| 225 if (m_state > 1 && m_extraHandlers.TryDequeue(out handler)) | |
| 157 // if the promise have been resolved while we was adding the handler to the queue | 226 // if the promise have been resolved while we was adding the handler to the queue |
| 158 // we can't guarantee that someone is still processing it | 227 // we can't guarantee that someone is still processing it |
| 159 // therefore we need to fetch a handler from the queue and execute it | 228 // therefore we need to fetch a handler from the queue and execute it |
| 160 // note that fetched handler may be not the one that we have added | 229 // note that fetched handler may be not the one that we have added |
| 161 // even we can fetch no handlers at all :) | 230 // even we can fetch no handlers at all :) |
| 162 InvokeHandler(handler); | 231 InvokeHandler(handler); |
| 232 } | |
| 163 } | 233 } |
| 164 } | 234 } |
| 165 | 235 |
| 166 protected void InvokeHandler(THandler handler) { | 236 protected void InvokeHandler(THandler handler) { |
| 167 switch (m_state) { | 237 switch (m_state) { |
