annotate Implab/AbstractPromise.cs @ 138:f75cfa58e3d4 v2

added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
author cin
date Tue, 17 Feb 2015 18:16:26 +0300
parents 671f60cd0250
children 16f926ee499d
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
1 using System;
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
2 using Implab.Parallels;
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
3 using System.Threading;
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
4 using System.Reflection;
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
5
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
6 namespace Implab {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
7 public abstract class AbstractPromise<THandler> {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
8
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
9 const int UNRESOLVED_SATE = 0;
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
10 const int TRANSITIONAL_STATE = 1;
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
11 const int SUCCEEDED_STATE = 2;
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
12 const int REJECTED_STATE = 3;
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
13 const int CANCELLED_STATE = 4;
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
14
125
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
15 const int RESERVED_HANDLERS_COUNT = 4;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
16
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
17 int m_state;
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
18 Exception m_error;
125
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
19 int m_handlersCount;
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
20
125
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
21 readonly THandler[] m_handlers = new THandler[RESERVED_HANDLERS_COUNT];
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
22 MTQueue<THandler> m_extraHandlers;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
23 int m_handlerPointer = -1;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
24 int m_handlersCommited;
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
25
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
26 #region state managment
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
27 bool BeginTransit() {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
28 return UNRESOLVED_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, UNRESOLVED_SATE);
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
29 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
30
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
31 void CompleteTransit(int state) {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
32 if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, state, TRANSITIONAL_STATE))
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
33 throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state");
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
34 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
35
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
36 void WaitTransition() {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
37 while (m_state == TRANSITIONAL_STATE) {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
38 Thread.MemoryBarrier();
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
39 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
40 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
41
130
671f60cd0250 fixed Resove method bug when calling it on already cancelled promise
cin
parents: 125
diff changeset
42 protected bool BeginSetResult() {
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
43 if (!BeginTransit()) {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
44 WaitTransition();
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
45 if (m_state != CANCELLED_STATE)
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
46 throw new InvalidOperationException("The promise is already resolved");
130
671f60cd0250 fixed Resove method bug when calling it on already cancelled promise
cin
parents: 125
diff changeset
47 return false;
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
48 }
130
671f60cd0250 fixed Resove method bug when calling it on already cancelled promise
cin
parents: 125
diff changeset
49 return true;
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
50 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
51
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
52 protected void EndSetResult() {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
53 CompleteTransit(SUCCEEDED_STATE);
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
54 OnSuccess();
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
55 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
56
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
57
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
58
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
59 /// <summary>
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
60 /// Выполняет обещание, сообщая об ошибке
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
61 /// </summary>
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
62 /// <remarks>
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
63 /// Поскольку обещание должно работать в многопточной среде, при его выполнении сразу несколько потоков
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
64 /// могу вернуть ошибку, при этом только первая будет использована в качестве результата, остальные
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
65 /// будут проигнорированы.
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
66 /// </remarks>
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
67 /// <param name="error">Исключение возникшее при выполнении операции</param>
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
68 /// <exception cref="InvalidOperationException">Данное обещание уже выполнено</exception>
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
69 protected void SetError(Exception error) {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
70 if (BeginTransit()) {
138
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
71 if (error is OperationCanceledException) {
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
72 CompleteTransit(CANCELLED_STATE);
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
73 m_error = error.InnerException;
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
74 OnCancelled();
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
75 } else {
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
76 m_error = error is PromiseTransientException ? error.InnerException : error;
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
77 CompleteTransit(REJECTED_STATE);
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
78 OnError();
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
79 }
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
80 } else {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
81 WaitTransition();
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
82 if (m_state == SUCCEEDED_STATE)
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
83 throw new InvalidOperationException("The promise is already resolved");
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
84 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
85 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
86
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
87 /// <summary>
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
88 /// Отменяет операцию, если это возможно.
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
89 /// </summary>
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
90 /// <remarks>Для определения была ли операция отменена следует использовать свойство <see cref="IsCancelled"/>.</remarks>
138
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
91 protected void SetCancelled(Exception reason) {
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
92 if (BeginTransit()) {
138
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
93 m_error = reason;
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
94 CompleteTransit(CANCELLED_STATE);
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
95 OnCancelled();
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
96 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
97 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
98
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
99 protected abstract void SignalSuccess(THandler handler);
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
100
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
101 protected abstract void SignalError(THandler handler, Exception error);
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
102
138
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
103 protected abstract void SignalCancelled(THandler handler, Exception reason);
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
104
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
105 void OnSuccess() {
125
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
106 var hp = m_handlerPointer;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
107 var slot = hp +1 ;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
108 while (slot < m_handlersCommited) {
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
109 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) {
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
110 SignalSuccess(m_handlers[slot]);
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
111 }
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
112 hp = m_handlerPointer;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
113 slot = hp +1 ;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
114 }
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
115
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
116
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
117 if (m_extraHandlers != null) {
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
118 THandler handler;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
119 while (m_extraHandlers.TryDequeue(out handler))
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
120 SignalSuccess(handler);
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
121 }
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
122 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
123
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
124 void OnError() {
125
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
125 var hp = m_handlerPointer;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
126 var slot = hp +1 ;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
127 while (slot < m_handlersCommited) {
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
128 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) {
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
129 SignalError(m_handlers[slot],m_error);
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
130 }
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
131 hp = m_handlerPointer;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
132 slot = hp +1 ;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
133 }
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
134
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
135 if (m_extraHandlers != null) {
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
136 THandler handler;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
137 while (m_extraHandlers.TryDequeue(out handler))
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
138 SignalError(handler, m_error);
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
139 }
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
140 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
141
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
142 void OnCancelled() {
125
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
143 var hp = m_handlerPointer;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
144 var slot = hp +1 ;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
145 while (slot < m_handlersCommited) {
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
146 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) {
138
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
147 SignalCancelled(m_handlers[slot], m_error);
125
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
148 }
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
149 hp = m_handlerPointer;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
150 slot = hp +1 ;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
151 }
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
152
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
153 if (m_extraHandlers != null) {
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
154 THandler handler;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
155 while (m_extraHandlers.TryDequeue(out handler))
138
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
156 SignalCancelled(handler, m_error);
125
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
157 }
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
158 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
159
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
160 #endregion
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
161
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
162 protected abstract void Listen(PromiseEventType events, Action handler);
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
163
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
164 #region synchronization traits
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
165 protected void WaitResult(int timeout) {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
166 if (!IsResolved) {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
167 var lk = new object();
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
168
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
169 Listen(PromiseEventType.All, () => {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
170 lock(lk) {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
171 Monitor.Pulse(lk);
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
172 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
173 });
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
174
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
175 lock (lk) {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
176 while(!IsResolved) {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
177 if(!Monitor.Wait(lk,timeout))
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
178 throw new TimeoutException();
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
179 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
180 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
181
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
182 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
183 switch (m_state) {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
184 case SUCCEEDED_STATE:
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
185 return;
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
186 case CANCELLED_STATE:
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
187 throw new OperationCanceledException();
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
188 case REJECTED_STATE:
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
189 throw new TargetInvocationException(m_error);
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
190 default:
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
191 throw new ApplicationException(String.Format("Invalid promise state {0}", m_state));
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
192 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
193 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
194 #endregion
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
195
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
196 #region handlers managment
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
197
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
198 protected void AddHandler(THandler handler) {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
199
125
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
200 if (m_state > 1) {
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
201 // the promise is in the resolved state, just invoke the handler
125
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
202 InvokeHandler(handler);
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
203 } else {
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
204 var slot = Interlocked.Increment(ref m_handlersCount) - 1;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
205
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
206 if (slot < RESERVED_HANDLERS_COUNT) {
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
207 m_handlers[slot] = handler;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
208
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
209 while (slot != Interlocked.CompareExchange(ref m_handlersCommited, slot + 1, slot)) {
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
210 }
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
211
125
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
212 if (m_state > 1) {
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
213 do {
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
214 var hp = m_handlerPointer;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
215 slot = hp + 1;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
216 if (slot < m_handlersCommited) {
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
217 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) != hp)
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
218 continue;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
219 InvokeHandler(m_handlers[slot]);
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
220 }
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
221 break;
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
222 } while(true);
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
223 }
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
224 } else {
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
225 if (slot == RESERVED_HANDLERS_COUNT) {
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
226 m_extraHandlers = new MTQueue<THandler>();
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
227 } else {
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
228 while (m_extraHandlers == null)
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
229 Thread.MemoryBarrier();
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
230 }
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
231
125
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
232 m_extraHandlers.Enqueue(handler);
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
233
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
234 if (m_state > 1 && m_extraHandlers.TryDequeue(out handler))
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
235 // if the promise have been resolved while we was adding the handler to the queue
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
236 // we can't guarantee that someone is still processing it
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
237 // therefore we need to fetch a handler from the queue and execute it
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
238 // note that fetched handler may be not the one that we have added
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
239 // even we can fetch no handlers at all :)
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
240 InvokeHandler(handler);
125
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
241 }
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
242 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
243 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
244
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
245 protected void InvokeHandler(THandler handler) {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
246 switch (m_state) {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
247 case SUCCEEDED_STATE:
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
248 SignalSuccess(handler);
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
249 break;
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
250 case CANCELLED_STATE:
138
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
251 SignalCancelled(handler, m_error);
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
252 break;
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
253 case REJECTED_STATE:
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
254 SignalError(handler, m_error);
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
255 break;
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
256 default:
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
257 throw new Exception(String.Format("Invalid promise state {0}", m_state));
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
258 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
259 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
260
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
261 #endregion
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
262
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
263 #region IPromise implementation
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
264
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
265 public void Join(int timeout) {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
266 WaitResult(timeout);
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
267 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
268
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
269 public void Join() {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
270 WaitResult(-1);
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
271 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
272
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
273 public bool IsResolved {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
274 get {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
275 Thread.MemoryBarrier();
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
276 return m_state > 1;
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
277 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
278 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
279
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
280 public bool IsCancelled {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
281 get {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
282 Thread.MemoryBarrier();
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
283 return m_state == CANCELLED_STATE;
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
284 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
285 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
286
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
287 #endregion
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
288
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
289 #region ICancellable implementation
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
290
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
291 public void Cancel() {
138
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
292 SetCancelled(null);
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
293 }
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
294
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
295 public void Cancel(Exception reason) {
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
296 SetCancelled(reason);
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
297 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
298
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
299 #endregion
138
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
300
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
301 public Exception Error {
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
302 get {
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
303 return m_error;
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
304 }
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
305 }
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
306 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
307 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
308