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