##// END OF EJS Templates
DRAFT: refactoring
cin -
r144:8c0b95069066 v2
parent child
Show More
@@ -0,0 +1,350
1 using System;
2 using Implab.Parallels;
3 using System.Threading;
4 using System.Reflection;
5
6 namespace Implab {
7 public abstract class AbstractEvent<THandler> : ICancelationToken, ICancellable {
8
9 const int UNRESOLVED_SATE = 0;
10 const int TRANSITIONAL_STATE = 1;
11 const int SUCCEEDED_STATE = 2;
12 const int REJECTED_STATE = 3;
13 const int CANCELLED_STATE = 4;
14
15 const int CANCEL_NOT_REQUESTED = 0;
16 const int CANCEL_REQUESTING = 1;
17 const int CANCEL_REQUESTED = 2;
18
19 const int RESERVED_HANDLERS_COUNT = 4;
20
21 int m_state;
22 Exception m_error;
23 int m_handlersCount;
24
25 readonly THandler[] m_handlers = new THandler[RESERVED_HANDLERS_COUNT];
26 MTQueue<THandler> m_extraHandlers;
27 int m_handlerPointer = -1;
28 int m_handlersCommited;
29
30 int m_cancelRequest;
31 Exception m_cancelationReason;
32 MTQueue<Action<Exception>> m_cancelationHandlers;
33
34
35 #region state managment
36 bool BeginTransit() {
37 return UNRESOLVED_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, UNRESOLVED_SATE);
38 }
39
40 void CompleteTransit(int state) {
41 if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, state, TRANSITIONAL_STATE))
42 throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state");
43 }
44
45 void WaitTransition() {
46 while (m_state == TRANSITIONAL_STATE) {
47 Thread.MemoryBarrier();
48 }
49 }
50
51 protected bool BeginSetResult() {
52 if (!BeginTransit()) {
53 WaitTransition();
54 if (m_state != CANCELLED_STATE)
55 throw new InvalidOperationException("The promise is already resolved");
56 return false;
57 }
58 return true;
59 }
60
61 protected void EndSetResult() {
62 CompleteTransit(SUCCEEDED_STATE);
63 OnSuccess();
64 }
65
66
67
68 /// <summary>
69 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ошибкС
70 /// </summary>
71 /// <remarks>
72 /// ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС, ΠΏΡ€ΠΈ Π΅Π³ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ сразу нСсколько ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²
73 /// ΠΌΠΎΠ³Ρƒ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ, ΠΏΡ€ΠΈ этом Ρ‚ΠΎΠ»ΡŒΠΊΠΎ пСрвая Π±ΡƒΠ΄Π΅Ρ‚ использована Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅
74 /// Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΡ€ΠΎΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹.
75 /// </remarks>
76 /// <param name="error">Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ</param>
77 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
78 protected void SetError(Exception error) {
79 if (BeginTransit()) {
80 if (error is OperationCanceledException) {
81 CompleteTransit(CANCELLED_STATE);
82 m_error = error.InnerException;
83 OnCancelled();
84 } else {
85 m_error = error is PromiseTransientException ? error.InnerException : error;
86 CompleteTransit(REJECTED_STATE);
87 OnError();
88 }
89 } else {
90 WaitTransition();
91 if (m_state == SUCCEEDED_STATE)
92 throw new InvalidOperationException("The promise is already resolved");
93 }
94 }
95
96 /// <summary>
97 /// ΠžΡ‚ΠΌΠ΅Π½ΡΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.
98 /// </summary>
99 /// <remarks>Для опрСдСлСния Π±Ρ‹Π»Π° Π»ΠΈ опСрация ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Π° слСдуСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ свойство <see cref="IsCancelled"/>.</remarks>
100 protected void SetCancelled(Exception reason) {
101 if (BeginTransit()) {
102 m_error = reason;
103 CompleteTransit(CANCELLED_STATE);
104 OnCancelled();
105 }
106 }
107
108 protected abstract void SignalSuccess(THandler handler);
109
110 protected abstract void SignalError(THandler handler, Exception error);
111
112 protected abstract void SignalCancelled(THandler handler, Exception reason);
113
114 void OnSuccess() {
115 var hp = m_handlerPointer;
116 var slot = hp +1 ;
117 while (slot < m_handlersCommited) {
118 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) {
119 SignalSuccess(m_handlers[slot]);
120 }
121 hp = m_handlerPointer;
122 slot = hp +1 ;
123 }
124
125
126 if (m_extraHandlers != null) {
127 THandler handler;
128 while (m_extraHandlers.TryDequeue(out handler))
129 SignalSuccess(handler);
130 }
131 }
132
133 void OnError() {
134 var hp = m_handlerPointer;
135 var slot = hp +1 ;
136 while (slot < m_handlersCommited) {
137 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) {
138 SignalError(m_handlers[slot],m_error);
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 SignalError(handler, m_error);
148 }
149 }
150
151 void OnCancelled() {
152 var hp = m_handlerPointer;
153 var slot = hp +1 ;
154 while (slot < m_handlersCommited) {
155 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) {
156 SignalCancelled(m_handlers[slot], m_error);
157 }
158 hp = m_handlerPointer;
159 slot = hp +1 ;
160 }
161
162 if (m_extraHandlers != null) {
163 THandler handler;
164 while (m_extraHandlers.TryDequeue(out handler))
165 SignalCancelled(handler, m_error);
166 }
167 }
168
169 #endregion
170
171 protected abstract Signal GetResolveSignal();
172
173 #region synchronization traits
174 protected void WaitResult(int timeout) {
175 if (!IsResolved)
176 GetResolveSignal().Wait(timeout);
177
178 switch (m_state) {
179 case SUCCEEDED_STATE:
180 return;
181 case CANCELLED_STATE:
182 throw new OperationCanceledException();
183 case REJECTED_STATE:
184 throw new TargetInvocationException(m_error);
185 default:
186 throw new ApplicationException(String.Format("Invalid promise state {0}", m_state));
187 }
188 }
189 #endregion
190
191 #region handlers managment
192
193 protected void AddHandler(THandler handler) {
194
195 if (m_state > 1) {
196 // the promise is in the resolved state, just invoke the handler
197 InvokeHandler(handler);
198 } else {
199 var slot = Interlocked.Increment(ref m_handlersCount) - 1;
200
201 if (slot < RESERVED_HANDLERS_COUNT) {
202
203 m_handlers[slot] = handler;
204
205 while (slot != Interlocked.CompareExchange(ref m_handlersCommited, slot + 1, slot)) {
206 }
207
208 if (m_state > 1) {
209 do {
210 var hp = m_handlerPointer;
211 slot = hp + 1;
212 if (slot < m_handlersCommited) {
213 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) != hp)
214 continue;
215 InvokeHandler(m_handlers[slot]);
216 }
217 break;
218 } while(true);
219 }
220 } else {
221 if (slot == RESERVED_HANDLERS_COUNT) {
222 m_extraHandlers = new MTQueue<THandler>();
223 } else {
224 while (m_extraHandlers == null)
225 Thread.MemoryBarrier();
226 }
227
228 m_extraHandlers.Enqueue(handler);
229
230 if (m_state > 1 && m_extraHandlers.TryDequeue(out handler))
231 // if the promise have been resolved while we was adding the handler to the queue
232 // we can't guarantee that someone is still processing it
233 // therefore we need to fetch a handler from the queue and execute it
234 // note that fetched handler may be not the one that we have added
235 // even we can fetch no handlers at all :)
236 InvokeHandler(handler);
237 }
238 }
239 }
240
241 protected void InvokeHandler(THandler handler) {
242 switch (m_state) {
243 case SUCCEEDED_STATE:
244 SignalSuccess(handler);
245 break;
246 case CANCELLED_STATE:
247 SignalCancelled(handler, m_error);
248 break;
249 case REJECTED_STATE:
250 SignalError(handler, m_error);
251 break;
252 default:
253 throw new Exception(String.Format("Invalid promise state {0}", m_state));
254 }
255 }
256
257 #endregion
258
259 #region IPromise implementation
260
261 public bool IsResolved {
262 get {
263 Thread.MemoryBarrier();
264 return m_state > 1;
265 }
266 }
267
268 public bool IsCancelled {
269 get {
270 Thread.MemoryBarrier();
271 return m_state == CANCELLED_STATE;
272 }
273 }
274
275 #endregion
276
277 public Exception Error {
278 get {
279 return m_error;
280 }
281 }
282
283 public bool AcceptIfRequested() {
284 if (IsCancelRequested)
285 CancelOperation(CancelReason);
286 }
287
288 public virtual void CancelOperation(Exception reason) {
289 SetCancelled(reason);
290 }
291
292 public void CancelationRequested(Action<Exception> handler) {
293 Safe.ArgumentNotNull(handler, "handler");
294 if (IsCancelRequested)
295 handler(CancelReason);
296
297 if (m_cancelationHandlers == null)
298 Interlocked.CompareExchange(ref m_cancelationHandlers, new MTQueue<Action<Exception>>(), null);
299
300 m_cancelationHandlers.Enqueue(handler);
301
302 if (IsCancelRequested && m_cancelationHandlers.TryDequeue(out handler))
303 // TryDeque implies MemoryBarrier()
304 handler(m_cancelationReason);
305 }
306
307 public bool IsCancelRequested {
308 get {
309 do {
310 if (m_cancelRequest == CANCEL_NOT_REQUESTED)
311 return false;
312 if (m_cancelRequest == CANCEL_REQUESTED)
313 return true;
314 Thread.MemoryBarrier();
315 } while(true);
316 }
317 }
318
319 public Exception CancelReason {
320 get {
321 do {
322 Thread.MemoryBarrier();
323 } while(m_cancelRequest == CANCEL_REQUESTING);
324
325 return m_cancelationReason;
326 }
327 }
328
329 #region ICancellable implementation
330
331 public void Cancel() {
332 Cancel(null);
333 }
334
335 public void Cancel(Exception reason) {
336 if (CANCEL_NOT_REQUESTED == Interlocked.CompareExchange(ref m_cancelRequest, CANCEL_REQUESTING)) {
337 m_cancelationReason = reason;
338 m_cancelRequest = CANCEL_REQUESTED;
339 if (m_cancelationHandlers != null) {
340 Action<Exception> handler;
341 while (m_cancelationHandlers.TryDequeue(out handler))
342 handler(m_cancelationReason);
343 }
344 }
345 }
346
347 #endregion
348 }
349 }
350
@@ -0,0 +1,185
1 using System;
2 using Implab.Parallels;
3
4 namespace Implab {
5 public abstract class AbstractPromise<T> : AbstractEvent<AbstractPromise<T>.HandlerDescriptor>, IPromise<T> {
6 public struct HandlerDescriptor {
7 readonly Action m_handler;
8 readonly Action<T> m_success;
9 readonly Action<Exception> m_error;
10 readonly Action<Exception> m_cancel;
11 readonly PromiseEventType m_mask;
12
13 public HandlerDescriptor(Action<T> success, Action<Exception> error, Action<Exception> cancel) {
14 m_success = success;
15 m_error = error;
16 m_cancel = cancel;
17 }
18
19 public HandlerDescriptor(Action success, Action<Exception> error, Action<Exception> cancel) {
20 m_handler = success;
21 m_error = error;
22 m_cancel = cancel;
23 m_mask = PromiseEventType.Success;
24 }
25
26 public HandlerDescriptor(Action handler, PromiseEventType mask) {
27 m_handler = handler;
28 m_mask = mask;
29 }
30
31 public void SignalSuccess(T result) {
32 if (m_success != null) {
33 try {
34 m_success(result);
35 } catch(Exception err) {
36 SignalError(err);
37 }
38 } else if (m_mask & PromiseEventType.Success && m_handler != null) {
39 try {
40 m_handler();
41 } catch(Exception err) {
42 // avoid calling handler twice in case of error
43 if (m_error != null)
44 SignalError(err);
45 }
46 }
47 }
48
49 public void SignalError(Exception err) {
50 if (m_error != null) {
51 try {
52 m_error(err);
53 // Analysis disable once EmptyGeneralCatchClause
54 } catch {
55 }
56 } else if (m_mask & PromiseEventType.Error && m_handler != null) {
57 try {
58 m_handler();
59 // Analysis disable once EmptyGeneralCatchClause
60 } catch {
61 }
62 }
63 }
64
65 public void SignalCancel(Exception reason) {
66 if (m_cancel != null) {
67 try {
68 m_cancel(reason);
69 } catch (Exception err) {
70 SignalError(err);
71 }
72 } else if (m_mask & PromiseEventType.Cancelled && m_handler != null) {
73 try {
74 m_handler();
75 // Analysis disable once EmptyGeneralCatchClause
76 } catch {
77 }
78 }
79 }
80 }
81
82
83
84 public Type PromiseType {
85 get {
86 return typeof(T);
87 }
88 }
89
90 public new T Join() {
91 WaitResult(-1);
92 return m_result;
93 }
94 public new T Join(int timeout) {
95 WaitResult(timeout);
96 return m_result;
97 }
98
99 public IPromise<T> On(Action<T> success, Action<Exception> error, Action<Exception> cancel) {
100 AddHandler(new HandlerDescriptor(success, error, cancel));
101 return this;
102 }
103
104 public IPromise<T> On(Action<T> success, Action<Exception> error) {
105 AddHandler(new HandlerDescriptor(success, error, null));
106 return this;
107 }
108
109 public IPromise<T> On(Action<T> success) {
110 AddHandler(new HandlerDescriptor(success, null, null));
111 return this;
112 }
113
114 public IPromise<T> On(Action handler, PromiseEventType events) {
115 AddHandler(new HandlerDescriptor(handler, events));
116 return this;
117 }
118
119 public IPromise<T> On(Action success, Action<Exception> error, Action<Exception> cancel) {
120 AddHandler(new HandlerDescriptor(success, error, cancel));
121 return this;
122 }
123
124 public IPromise<T> On(Action success, Action<Exception> error) {
125 AddHandler(new HandlerDescriptor(success, error, null));
126 return this;
127 }
128
129 public IPromise<T> On(Action success) {
130 AddHandler(new HandlerDescriptor(success, null, null));
131 return this;
132 }
133
134 IPromise IPromise.On(Action success, Action<Exception> error, Action<Exception> cancel) {
135 AddHandler(new HandlerDescriptor(success, error, cancel));
136 return this;
137 }
138
139 IPromise IPromise.On(Action success, Action<Exception> error) {
140 AddHandler(new HandlerDescriptor(success, error, null));
141 return this;
142 }
143
144 IPromise IPromise.On(Action success) {
145 AddHandler(new HandlerDescriptor(success, null, null));
146 return this;
147 }
148
149 public IPromise<T2> Cast<T2>() {
150 return (IPromise<T2>)this;
151 }
152
153 #region implemented abstract members of AbstractPromise
154
155 protected override Signal GetResolveSignal() {
156 var signal = new Signal();
157 AddHandler(new HandlerDescriptor(signal.Set, PromiseEventType.All));
158 return signal;
159 }
160
161 protected override void SignalSuccess(HandlerDescriptor handler) {
162 handler.SignalSuccess(m_result);
163 }
164
165 protected override void SignalError(HandlerDescriptor handler, Exception error) {
166 handler.SignalError(error);
167 }
168
169 protected override void SignalCancelled(HandlerDescriptor handler, Exception reason) {
170 handler.SignalCancel(reason);
171 }
172
173 #endregion
174
175 T m_result;
176
177 protected void SetResult(T value) {
178 if (BeginSetResult()) {
179 m_result = value;
180 EndSetResult();
181 }
182 }
183 }
184 }
185
@@ -0,0 +1,54
1 using System;
2 using System.Threading;
3
4 namespace Implab {
5 public class ChainTask : AbstractPromise, IDeferred {
6 readonly Func<IPromise> m_task;
7 readonly Action<Exception> m_error;
8 readonly Action<Exception> m_cancel;
9
10 int m_cancelationLock;
11
12 public ChainTask(Func<IPromise> task, Func<Exception> error, Func<Exception> cancel) {
13 m_task = task;
14 }
15
16 public void Resolve() {
17 if (m_task != null && LockCancelation()) {
18 try {
19 var operation = m_task();
20 if (operation == null)
21 throw new NullReferenceException("The task returned null promise");
22
23 operation.On(SetResult, SetError, SetCancelled);
24
25 CancelationRequested(operation.Cancel);
26 } catch(Exception err) {
27 HandleErrorInternal(err);
28 }
29 }
30 }
31
32 public void Reject(Exception error) {
33 throw new NotImplementedException();
34 }
35
36 protected void HandleErrorInternal(Exception error) {
37 if (m_error != null) {
38 try {
39 m_error(error);
40 SetResult();
41 } catch(Exception err) {
42 SetError(err);
43 }
44 } else {
45 SetError(error);
46 }
47 }
48
49 protected bool LockCancelation() {
50 return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0);
51 }
52 }
53 }
54
@@ -0,0 +1,23
1 using System;
2 using System.Threading;
3
4 namespace Implab {
5 public class FuncTask<T> : FuncTaskBase<T>, IDeferred {
6 readonly Func<T> m_task;
7
8 public FuncTask(Func<T> task, Func<Exception, T> error, Func<Exception, T> cancel) : base(error,cancel) {
9 m_task = task;
10 }
11
12 public void Resolve() {
13 if (m_task != null && LockCancelation()) {
14 try {
15 SetResult(m_task());
16 } catch(Exception err) {
17 HandleErrorInternal(err);
18 }
19 }
20 }
21 }
22 }
23
@@ -0,0 +1,53
1 using System;
2 using System.Threading;
3
4 namespace Implab {
5 public class FuncTaskBase<TResult> : AbstractPromise<TResult> {
6 readonly Func<Exception, TResult> m_cancel;
7 readonly Func<Exception, TResult> m_error;
8
9 int m_cancelationLock;
10
11 protected FuncTaskBase( Func<Exception, TResult> error, Func<Exception, TResult> cancel) {
12 m_error = error;
13 m_cancel = cancel;
14 }
15
16 public void Reject(Exception error) {
17 Safe.ArgumentNotNull(error, "error");
18 if (LockCancelation())
19 HandleErrorInternal(error);
20 }
21
22 protected void HandleErrorInternal(Exception error) {
23 if (m_error != null) {
24 try {
25 SetResult(m_error(error));
26 } catch(Exception err) {
27 SetError(err);
28 }
29 } else {
30 SetError(error);
31 }
32 }
33
34 public override void CancelOperation(Exception reason) {
35 if (LockCancelation()) {
36 if (m_cancel != null) {
37 try {
38 SetResult(m_cancel(reason));
39 } catch (Exception err) {
40 HandleErrorInternal(err);
41 }
42 } else {
43 SetCancelled(reason);
44 }
45 }
46 }
47
48 protected bool LockCancelation() {
49 return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0);
50 }
51 }
52 }
53
@@ -0,0 +1,22
1 using System;
2
3 namespace Implab {
4 public class FuncTask<TArg, TResult> : FuncTaskBase<TResult>, IDeferred<TArg> {
5 readonly Func<TArg, TResult> m_task;
6
7 public FuncTask(Func<TArg, TResult> task, Func<Exception, TResult> error,Func<Exception, TResult> cancel) : base(error,cancel) {
8 m_task = task;
9 }
10
11 public void Resolve(TArg value) {
12 if (m_task != null && LockCancelation()) {
13 try {
14 SetResult(m_task(value));
15 } catch (Exception err) {
16 HandleErrorInternal(err);
17 }
18 }
19 }
20 }
21 }
22
@@ -1,296 +1,136
1 1 using System;
2 2 using Implab.Parallels;
3 using System.Threading;
4 using System.Reflection;
5 3
6 4 namespace Implab {
7 public abstract class AbstractPromise<THandler> {
8
9 const int UNRESOLVED_SATE = 0;
10 const int TRANSITIONAL_STATE = 1;
11 const int SUCCEEDED_STATE = 2;
12 const int REJECTED_STATE = 3;
13 const int CANCELLED_STATE = 4;
14
15 const int RESERVED_HANDLERS_COUNT = 4;
5 public abstract class AbstractPromise : AbstractEvent<AbstractPromise.HandlerDescriptor>, IPromise {
6 public struct HandlerDescriptor {
7 readonly Action m_handler;
8 readonly Action<Exception> m_error;
9 readonly Action<Exception> m_cancel;
10 readonly PromiseEventType m_mask;
16 11
17 int m_state;
18 Exception m_error;
19 int m_handlersCount;
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;
25
26 #region state managment
27 bool BeginTransit() {
28 return UNRESOLVED_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, UNRESOLVED_SATE);
12 public HandlerDescriptor(Action success, Action<Exception> error, Action<Exception> cancel) {
13 m_handler = success;
14 m_error = error;
15 m_cancel = cancel;
16 m_mask = PromiseEventType.Success;
29 17 }
30 18
31 void CompleteTransit(int state) {
32 if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, state, TRANSITIONAL_STATE))
33 throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state");
19 public HandlerDescriptor(Action handler, PromiseEventType mask) {
20 m_handler = handler;
21 m_mask = mask;
34 22 }
35 23
36 void WaitTransition() {
37 while (m_state == TRANSITIONAL_STATE) {
38 Thread.MemoryBarrier();
24 public void SignalSuccess() {
25 if (m_mask & PromiseEventType.Success && m_handler != null) {
26 try {
27 m_handler();
28 } catch (Exception err) {
29 // avoid calling handler twice in case of error
30 if (m_error != null)
31 SignalError(err);
32 }
39 33 }
40 34 }
41 35
42 protected bool BeginSetResult() {
43 if (!BeginTransit()) {
44 WaitTransition();
45 if (m_state != CANCELLED_STATE)
46 throw new InvalidOperationException("The promise is already resolved");
47 return false;
36 public void SignalError(Exception err) {
37 if (m_error != null) {
38 try {
39 m_error(err);
40 // Analysis disable once EmptyGeneralCatchClause
41 } catch {
48 42 }
49 return true;
43 } else if (m_mask & PromiseEventType.Error && m_handler != null) {
44 try {
45 m_handler();
46 // Analysis disable once EmptyGeneralCatchClause
47 } catch {
48 }
49 }
50 50 }
51 51
52 protected void EndSetResult() {
53 CompleteTransit(SUCCEEDED_STATE);
54 OnSuccess();
52 public void SignalCancel(Exception reason) {
53 if (m_cancel != null) {
54 try {
55 m_cancel(reason);
56 } catch (Exception err) {
57 SignalError(err);
58 }
59 } else if (m_mask & PromiseEventType.Cancelled && m_handler != null) {
60 try {
61 m_handler();
62 // Analysis disable once EmptyGeneralCatchClause
63 } catch {
64 }
65 }
66 }
55 67 }
56 68
57 69
70 #region implemented abstract members of AbstractPromise
58 71
59 /// <summary>
60 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ошибкС
61 /// </summary>
62 /// <remarks>
63 /// ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС, ΠΏΡ€ΠΈ Π΅Π³ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ сразу нСсколько ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²
64 /// ΠΌΠΎΠ³Ρƒ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ, ΠΏΡ€ΠΈ этом Ρ‚ΠΎΠ»ΡŒΠΊΠΎ пСрвая Π±ΡƒΠ΄Π΅Ρ‚ использована Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅
65 /// Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΡ€ΠΎΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹.
66 /// </remarks>
67 /// <param name="error">Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ</param>
68 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
69 protected void SetError(Exception error) {
70 if (BeginTransit()) {
71 if (error is OperationCanceledException) {
72 CompleteTransit(CANCELLED_STATE);
73 m_error = error.InnerException;
74 OnCancelled();
75 } else {
76 m_error = error is PromiseTransientException ? error.InnerException : error;
77 CompleteTransit(REJECTED_STATE);
78 OnError();
79 }
80 } else {
81 WaitTransition();
82 if (m_state == SUCCEEDED_STATE)
83 throw new InvalidOperationException("The promise is already resolved");
84 }
85 }
86
87 /// <summary>
88 /// ΠžΡ‚ΠΌΠ΅Π½ΡΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.
89 /// </summary>
90 /// <remarks>Для опрСдСлСния Π±Ρ‹Π»Π° Π»ΠΈ опСрация ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Π° слСдуСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ свойство <see cref="IsCancelled"/>.</remarks>
91 protected void SetCancelled(Exception reason) {
92 if (BeginTransit()) {
93 m_error = reason;
94 CompleteTransit(CANCELLED_STATE);
95 OnCancelled();
96 }
72 protected override void SignalSuccess(HandlerDescriptor handler) {
73 handler.SignalSuccess();
97 74 }
98 75
99 protected abstract void SignalSuccess(THandler handler);
100
101 protected abstract void SignalError(THandler handler, Exception error);
102
103 protected abstract void SignalCancelled(THandler handler, Exception reason);
104
105 void OnSuccess() {
106 var hp = m_handlerPointer;
107 var slot = hp +1 ;
108 while (slot < m_handlersCommited) {
109 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) {
110 SignalSuccess(m_handlers[slot]);
111 }
112 hp = m_handlerPointer;
113 slot = hp +1 ;
114 }
115
116
117 if (m_extraHandlers != null) {
118 THandler handler;
119 while (m_extraHandlers.TryDequeue(out handler))
120 SignalSuccess(handler);
121 }
76 protected override void SignalError(HandlerDescriptor handler, Exception error) {
77 handler.SignalError(error);
122 78 }
123 79
124 void OnError() {
125 var hp = m_handlerPointer;
126 var slot = hp +1 ;
127 while (slot < m_handlersCommited) {
128 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) {
129 SignalError(m_handlers[slot],m_error);
130 }
131 hp = m_handlerPointer;
132 slot = hp +1 ;
80 protected override void SignalCancelled(HandlerDescriptor handler, Exception reason) {
81 handler.SignalCancel(reason);
133 82 }
134 83
135 if (m_extraHandlers != null) {
136 THandler handler;
137 while (m_extraHandlers.TryDequeue(out handler))
138 SignalError(handler, m_error);
139 }
140 }
141
142 void OnCancelled() {
143 var hp = m_handlerPointer;
144 var slot = hp +1 ;
145 while (slot < m_handlersCommited) {
146 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) {
147 SignalCancelled(m_handlers[slot], m_error);
148 }
149 hp = m_handlerPointer;
150 slot = hp +1 ;
151 }
152
153 if (m_extraHandlers != null) {
154 THandler handler;
155 while (m_extraHandlers.TryDequeue(out handler))
156 SignalCancelled(handler, m_error);
157 }
84 protected override Signal GetResolveSignal() {
85 var signal = new Signal();
86 On(signal.Set, PromiseEventType.All);
158 87 }
159 88
160 89 #endregion
161 90
162 protected abstract void Listen(PromiseEventType events, Action handler);
163 91
164 #region synchronization traits
165 protected void WaitResult(int timeout) {
166 if (!IsResolved) {
167 var lk = new object();
168
169 Listen(PromiseEventType.All, () => {
170 lock(lk) {
171 Monitor.Pulse(lk);
172 }
173 });
174
175 lock (lk) {
176 while(!IsResolved) {
177 if(!Monitor.Wait(lk,timeout))
178 throw new TimeoutException();
92 public Type PromiseType {
93 get {
94 return typeof(void);
179 95 }
180 96 }
181 97
98 public IPromise On(Action success, Action<Exception> error, Action<Exception> cancel) {
99 AddHandler(new HandlerDescriptor(success, error, cancel));
100 return this;
182 101 }
183 switch (m_state) {
184 case SUCCEEDED_STATE:
185 return;
186 case CANCELLED_STATE:
187 throw new OperationCanceledException();
188 case REJECTED_STATE:
189 throw new TargetInvocationException(m_error);
190 default:
191 throw new ApplicationException(String.Format("Invalid promise state {0}", m_state));
192 }
193 }
194 #endregion
195 102
196 #region handlers managment
197
198 protected void AddHandler(THandler handler) {
199
200 if (m_state > 1) {
201 // the promise is in the resolved state, just invoke the handler
202 InvokeHandler(handler);
203 } else {
204 var slot = Interlocked.Increment(ref m_handlersCount) - 1;
205
206 if (slot < RESERVED_HANDLERS_COUNT) {
207 m_handlers[slot] = handler;
208
209 while (slot != Interlocked.CompareExchange(ref m_handlersCommited, slot + 1, slot)) {
103 public IPromise On(Action success, Action<Exception> error) {
104 AddHandler(new HandlerDescriptor(success, error, null));
105 return this;
210 106 }
211 107
212 if (m_state > 1) {
213 do {
214 var hp = m_handlerPointer;
215 slot = hp + 1;
216 if (slot < m_handlersCommited) {
217 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) != hp)
218 continue;
219 InvokeHandler(m_handlers[slot]);
220 }
221 break;
222 } while(true);
223 }
224 } else {
225 if (slot == RESERVED_HANDLERS_COUNT) {
226 m_extraHandlers = new MTQueue<THandler>();
227 } else {
228 while (m_extraHandlers == null)
229 Thread.MemoryBarrier();
108 public IPromise On(Action success) {
109 AddHandler(new HandlerDescriptor(success, null, null));
110 return this;
230 111 }
231 112
232 m_extraHandlers.Enqueue(handler);
233
234 if (m_state > 1 && m_extraHandlers.TryDequeue(out handler))
235 // if the promise have been resolved while we was adding the handler to the queue
236 // we can't guarantee that someone is still processing it
237 // therefore we need to fetch a handler from the queue and execute it
238 // note that fetched handler may be not the one that we have added
239 // even we can fetch no handlers at all :)
240 InvokeHandler(handler);
241 }
242 }
113 public IPromise On(Action handler, PromiseEventType events) {
114 AddHandler(new HandlerDescriptor(handler,events));
115 return this;
243 116 }
244 117
245 protected void InvokeHandler(THandler handler) {
246 switch (m_state) {
247 case SUCCEEDED_STATE:
248 SignalSuccess(handler);
249 break;
250 case CANCELLED_STATE:
251 SignalCancelled(handler, m_error);
252 break;
253 case REJECTED_STATE:
254 SignalError(handler, m_error);
255 break;
256 default:
257 throw new Exception(String.Format("Invalid promise state {0}", m_state));
258 }
259 }
260
261 #endregion
262
263 #region IPromise implementation
264
265 public void Join(int timeout) {
266 WaitResult(timeout);
118 public IPromise<T> Cast<T>() {
119 throw new InvalidCastException();
267 120 }
268 121
269 122 public void Join() {
270 123 WaitResult(-1);
271 124 }
272 125
273 public bool IsResolved {
274 get {
275 Thread.MemoryBarrier();
276 return m_state > 1;
277 }
126 public void Join(int timeout) {
127 WaitResult(timeout);
278 128 }
279 129
280 public bool IsCancelled {
281 get {
282 Thread.MemoryBarrier();
283 return m_state == CANCELLED_STATE;
284 }
285 }
286
287 #endregion
288
289 public Exception Error {
290 get {
291 return m_error;
292 }
130 protected void SetResult() {
131 BeginSetResult();
132 EndSetResult();
293 133 }
294 134 }
295 135 }
296 136
@@ -1,36 +1,36
1 1 using System;
2 2
3 3 namespace Implab {
4 4 public interface ICancelationToken {
5 5 /// <summary>
6 6 /// Indicates wherther the cancellation was requested.
7 7 /// </summary>
8 8 bool IsCancelRequested { get ; }
9 9
10 10 /// <summary>
11 11 /// The reason why the operation should be cancelled.
12 12 /// </summary>
13 13 Exception CancelReason { get ; }
14 14
15 15 /// <summary>
16 16 /// Accepts if requested.
17 17 /// </summary>
18 18 /// <returns><c>true</c>, if if requested was accepted, <c>false</c> otherwise.</returns>
19 19 bool AcceptIfRequested();
20 20
21 21 /// <summary>
22 22 /// Sets the token to cancelled state.
23 23 /// </summary>
24 24 /// <param name="reason">The reason why the operation was cancelled.</param>
25 void SetCancelled(Exception reason);
25 void CancelOperation(Exception reason);
26 26
27 27 /// <summary>
28 28 /// Adds the listener for the cancellation request, is the cancellation was requested the <paramref name="handler"/>
29 29 /// is executed immediatelly.
30 30 /// </summary>
31 31 /// <param name="handler">The handler which will be executed if the cancel occurs.</param>
32 void CancellationRequested(Action<Exception> handler);
32 void CancelationRequested(Action<Exception> handler);
33 33
34 34 }
35 35 }
36 36
@@ -1,106 +1,106
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.Linq;
4 4 using System.Text;
5 5
6 6 namespace Implab {
7 7 public interface IPromise: ICancellable {
8 8
9 9 /// <summary>
10 10 /// Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌΠΎΠ³ΠΎ Ρ‡Π΅Ρ€Π΅Π· Π΄Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅.
11 11 /// </summary>
12 12 Type PromiseType { get; }
13 13
14 14 /// <summary>
15 15 /// ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ являСтся Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Ρ‹ΠΌ, Π»ΠΈΠ±ΠΎ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ, Π»ΠΈΠ±ΠΎ с ошибкой, Π»ΠΈΠ±ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½ΠΎ.
16 16 /// </summary>
17 17 bool IsResolved { get; }
18 18
19 19 /// <summary>
20 20 /// ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±Ρ‹Π»ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½ΠΎ.
21 21 /// </summary>
22 22 bool IsCancelled { get; }
23 23
24 24 /// <summary>
25 25 /// Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС Π² Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ выполнСния обСщания, Π»ΠΈΠ±ΠΎ ΠΏΡ€ΠΈΡ‡ΠΈΠ½Π° ΠΎΡ‚ΠΌΠ΅Π½Ρ‹.
26 26 /// </summary>
27 27 Exception Error { get; }
28 28
29 29 /// <summary>
30 30 /// Creates a new promise dependend on the current one and resolved on
31 31 /// executing the specified handlers.
32 32 /// </summary>
33 33 /// <param name="success">The handler called on the successful promise completion.</param>
34 34 /// <param name="error">The handler is called if an error while completing the promise occurred.</param>
35 35 /// <param name="cancel">The handler is called in case of promise cancellation.</param>
36 36 /// <returns>The newly created dependant promise.</returns>
37 37 /// <remarks>
38 38 /// <para>
39 39 /// If the success handler is specified the dependend promise will be resolved after the handler is
40 40 /// executed and the dependent promise will be linked to the current one, i.e. the cancellation
41 41 /// of the dependent property will lead to the cancellation of the current promise. If the
42 42 /// success handler isn't specified the dependent promise will not be linked to and
43 43 /// will not be resolved after the successfull resolution of the current one.
44 44 /// </para>
45 45 /// <para>
46 46 /// When the error handler is specified, the exception raised during the current promise completion
47 47 /// will be passed to it as the parameter. If the error handler returns without raising an
48 48 /// exception then the dependant promise will be resolved successfully, otherwise the exception
49 49 /// raised by the handler will be transmitted to the dependent promise. If the handler wants
50 50 /// to passthrough the original exception it needs to wrap the exception with
51 51 /// the <see cref="PromiseTransientException"/>. The handler may raise <see cref="OperationCanceledException"/>
52 52 /// to cancel the dependant promise, the innner exception specifies the reason why the promise
53 53 /// is canceled.
54 54 /// </para>
55 55 /// <para>
56 56 /// If the cancelation handler is specified and the current promise is cancelled then the dependent
57 57 /// promise will be resolved after the handler is executed. If the cancelation handler raises the
58 58 /// exception it will be passed to the dependent promise.
59 59 /// </para>
60 60 /// </remarks>
61 IPromise Then(Action success, Action<Exception> error, Action<Exception> cancel);
61 /* IPromise Then(Action success, Action<Exception> error, Action<Exception> cancel);
62 62 IPromise Then(Action success, Action<Exception> error);
63 63 IPromise Then(Action success);
64 64
65 65 IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<Exception, IPromise> cancel);
66 66 IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error);
67 IPromise Chain(Func<IPromise> chained);
67 IPromise Chain(Func<IPromise> chained);*/
68 68
69 69 /// <summary>
70 70 /// Adds specified listeners to the current promise.
71 71 /// </summary>
72 72 /// <param name="success">The handler called on the successful promise completion.</param>
73 73 /// <param name="error">The handler is called if an error while completing the promise occurred.</param>
74 74 /// <param name="cancel">The handler is called in case of promise cancellation.</param>
75 75 /// <returns>The current promise.</returns>
76 76 IPromise On(Action success, Action<Exception> error, Action<Exception> cancel);
77 77 IPromise On(Action success, Action<Exception> error);
78 78 IPromise On(Action success);
79 79
80 80 /// <summary>
81 81 /// Adds specified listeners to the current promise.
82 82 /// </summary>
83 83 /// <param name="handler">The handler called on the specified events.</param>
84 84 /// <param name = "events">The combination of flags denoting the events for which the
85 85 /// handler shoud be called.</param>
86 86 /// <returns>The current promise.</returns>
87 87 IPromise On(Action handler, PromiseEventType events);
88 88
89 89 /// <summary>
90 90 /// ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ обСщания ΠΊ Π·Π°Π΄Π°Π½Π½ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅.
91 91 /// </summary>
92 92 IPromise<T> Cast<T>();
93 93
94 94 /// <summary>
95 95 /// Π‘ΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ с ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ΠΌ.
96 96 /// </summary>
97 97 void Join();
98 98 /// <summary>
99 99 /// Π‘ΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ с ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ΠΌ.
100 100 /// </summary>
101 101 /// <param name="timeout">ВрСмя оТидания, ΠΏΠΎ Π΅Π³ΠΎ ΠΈΡΡ‚Π΅Ρ‡Π΅Π½ΠΈΡŽ Π²ΠΎΠ·Π½ΠΈΠΊΠ½Π΅Ρ‚ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.</param>
102 102 /// <exception cref="TimeoutException">ΠŸΡ€Π΅Π²Ρ‹ΡˆΠ΅Π½ΠΎ врСмя оТидания.</exception>
103 103 void Join(int timeout);
104 104
105 105 }
106 106 }
@@ -1,30 +1,25
1 1 using System;
2 2
3 3 namespace Implab {
4 4 public interface IPromise<out T> : IPromise {
5 5
6 new T Join();
7
8 new T Join(int timeout);
9
10 6 IPromise<T> On(Action<T> success, Action<Exception> error, Action<Exception> cancel);
11 7
12 8 IPromise<T> On(Action<T> success, Action<Exception> error);
13 9
14 10 IPromise<T> On(Action<T> success);
15 11
12 new T Join();
13
14 new T Join(int timeout);
15
16 new IPromise<T> On(Action success, Action<Exception> error, Action<Exception> cancel);
17
18 new IPromise<T> On(Action success, Action<Exception> error);
19
20 new IPromise<T> On(Action success);
21
16 22 new IPromise<T> On(Action handler, PromiseEventType events);
17 23
18 IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error, Func<Exception, T2> cancel);
19
20 IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error);
21
22 IPromise<T2> Then<T2>(Func<T, T2> mapper);
23
24 IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception, IPromise<T2>> error, Func<Exception, IPromise<T2>> cancel);
25
26 IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception, IPromise<T2>> error);
27
28 IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained);
29 24 }
30 25 }
@@ -1,234 +1,240
1 1 ο»Ώ<?xml version="1.0" encoding="utf-8"?>
2 2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 3 <PropertyGroup>
4 4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5 5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6 6 <ProjectGuid>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</ProjectGuid>
7 7 <OutputType>Library</OutputType>
8 8 <RootNamespace>Implab</RootNamespace>
9 9 <AssemblyName>Implab</AssemblyName>
10 10 <ProductVersion>8.0.30703</ProductVersion>
11 11 <SchemaVersion>2.0</SchemaVersion>
12 12 </PropertyGroup>
13 13 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
14 14 <DebugSymbols>true</DebugSymbols>
15 15 <DebugType>full</DebugType>
16 16 <Optimize>false</Optimize>
17 17 <OutputPath>bin\Debug</OutputPath>
18 18 <DefineConstants>TRACE;DEBUG;</DefineConstants>
19 19 <ErrorReport>prompt</ErrorReport>
20 20 <WarningLevel>4</WarningLevel>
21 21 <ConsolePause>false</ConsolePause>
22 22 <RunCodeAnalysis>true</RunCodeAnalysis>
23 23 </PropertyGroup>
24 24 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
25 25 <DebugType>full</DebugType>
26 26 <Optimize>true</Optimize>
27 27 <OutputPath>bin\Release</OutputPath>
28 28 <ErrorReport>prompt</ErrorReport>
29 29 <WarningLevel>4</WarningLevel>
30 30 <ConsolePause>false</ConsolePause>
31 31 </PropertyGroup>
32 32 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' ">
33 33 <DebugSymbols>true</DebugSymbols>
34 34 <DebugType>full</DebugType>
35 35 <Optimize>false</Optimize>
36 36 <OutputPath>bin\Debug</OutputPath>
37 37 <DefineConstants>TRACE;DEBUG;NET_4_5</DefineConstants>
38 38 <ErrorReport>prompt</ErrorReport>
39 39 <WarningLevel>4</WarningLevel>
40 40 <RunCodeAnalysis>true</RunCodeAnalysis>
41 41 <ConsolePause>false</ConsolePause>
42 42 </PropertyGroup>
43 43 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' ">
44 44 <Optimize>true</Optimize>
45 45 <OutputPath>bin\Release</OutputPath>
46 46 <ErrorReport>prompt</ErrorReport>
47 47 <WarningLevel>4</WarningLevel>
48 48 <ConsolePause>false</ConsolePause>
49 49 <DefineConstants>NET_4_5</DefineConstants>
50 50 </PropertyGroup>
51 51 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugMono|AnyCPU' ">
52 52 <DebugSymbols>true</DebugSymbols>
53 53 <DebugType>full</DebugType>
54 54 <Optimize>false</Optimize>
55 55 <OutputPath>bin\Debug</OutputPath>
56 56 <DefineConstants>TRACE;DEBUG;NET_4_5;MONO</DefineConstants>
57 57 <ErrorReport>prompt</ErrorReport>
58 58 <WarningLevel>4</WarningLevel>
59 59 <RunCodeAnalysis>true</RunCodeAnalysis>
60 60 <ConsolePause>false</ConsolePause>
61 61 </PropertyGroup>
62 62 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseMono|AnyCPU' ">
63 63 <Optimize>true</Optimize>
64 64 <OutputPath>bin\Release</OutputPath>
65 65 <DefineConstants>NET_4_5;MONO;</DefineConstants>
66 66 <ErrorReport>prompt</ErrorReport>
67 67 <WarningLevel>4</WarningLevel>
68 68 <ConsolePause>false</ConsolePause>
69 69 </PropertyGroup>
70 70 <ItemGroup>
71 71 <Reference Include="System" />
72 72 <Reference Include="System.Xml" />
73 73 </ItemGroup>
74 74 <ItemGroup>
75 75 <Compile Include="Component.cs" />
76 76 <Compile Include="CustomEqualityComparer.cs" />
77 77 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
78 78 <Compile Include="Diagnostics\EventText.cs" />
79 79 <Compile Include="Diagnostics\LogChannel.cs" />
80 80 <Compile Include="Diagnostics\LogicalOperation.cs" />
81 81 <Compile Include="Diagnostics\TextFileListener.cs" />
82 82 <Compile Include="Diagnostics\TraceLog.cs" />
83 83 <Compile Include="Diagnostics\TraceEvent.cs" />
84 84 <Compile Include="Diagnostics\TraceEventType.cs" />
85 85 <Compile Include="Disposable.cs" />
86 86 <Compile Include="ICancellable.cs" />
87 87 <Compile Include="IProgressHandler.cs" />
88 88 <Compile Include="IProgressNotifier.cs" />
89 89 <Compile Include="IPromiseT.cs" />
90 90 <Compile Include="IPromise.cs" />
91 91 <Compile Include="IServiceLocator.cs" />
92 92 <Compile Include="ITaskController.cs" />
93 93 <Compile Include="JSON\JSONElementContext.cs" />
94 94 <Compile Include="JSON\JSONElementType.cs" />
95 95 <Compile Include="JSON\JSONGrammar.cs" />
96 96 <Compile Include="JSON\JSONParser.cs" />
97 97 <Compile Include="JSON\JSONScanner.cs" />
98 98 <Compile Include="JSON\JsonTokenType.cs" />
99 99 <Compile Include="JSON\JSONWriter.cs" />
100 100 <Compile Include="JSON\JSONXmlReader.cs" />
101 101 <Compile Include="JSON\JSONXmlReaderOptions.cs" />
102 102 <Compile Include="JSON\StringTranslator.cs" />
103 103 <Compile Include="Parallels\DispatchPool.cs" />
104 104 <Compile Include="Parallels\ArrayTraits.cs" />
105 105 <Compile Include="Parallels\MTQueue.cs" />
106 106 <Compile Include="Parallels\WorkerPool.cs" />
107 107 <Compile Include="Parsing\Alphabet.cs" />
108 108 <Compile Include="Parsing\AlphabetBase.cs" />
109 109 <Compile Include="Parsing\AltToken.cs" />
110 110 <Compile Include="Parsing\BinaryToken.cs" />
111 111 <Compile Include="Parsing\CatToken.cs" />
112 112 <Compile Include="Parsing\CDFADefinition.cs" />
113 113 <Compile Include="Parsing\DFABuilder.cs" />
114 114 <Compile Include="Parsing\DFADefinitionBase.cs" />
115 115 <Compile Include="Parsing\DFAStateDescriptor.cs" />
116 116 <Compile Include="Parsing\DFAutomaton.cs" />
117 117 <Compile Include="Parsing\EDFADefinition.cs" />
118 118 <Compile Include="Parsing\EmptyToken.cs" />
119 119 <Compile Include="Parsing\EndToken.cs" />
120 120 <Compile Include="Parsing\EnumAlphabet.cs" />
121 121 <Compile Include="Parsing\Grammar.cs" />
122 122 <Compile Include="Parsing\IAlphabet.cs" />
123 123 <Compile Include="Parsing\IDFADefinition.cs" />
124 124 <Compile Include="Parsing\IVisitor.cs" />
125 125 <Compile Include="Parsing\ParserException.cs" />
126 126 <Compile Include="Parsing\Scanner.cs" />
127 127 <Compile Include="Parsing\StarToken.cs" />
128 128 <Compile Include="Parsing\SymbolToken.cs" />
129 129 <Compile Include="Parsing\Token.cs" />
130 130 <Compile Include="ServiceLocator.cs" />
131 131 <Compile Include="TaskController.cs" />
132 132 <Compile Include="ProgressInitEventArgs.cs" />
133 133 <Compile Include="Properties\AssemblyInfo.cs" />
134 134 <Compile Include="Parallels\AsyncPool.cs" />
135 135 <Compile Include="Safe.cs" />
136 136 <Compile Include="ValueEventArgs.cs" />
137 137 <Compile Include="PromiseExtensions.cs" />
138 138 <Compile Include="SyncContextPromise.cs" />
139 139 <Compile Include="Diagnostics\OperationContext.cs" />
140 140 <Compile Include="Diagnostics\TraceContext.cs" />
141 141 <Compile Include="Diagnostics\LogEventArgs.cs" />
142 142 <Compile Include="Diagnostics\LogEventArgsT.cs" />
143 143 <Compile Include="Diagnostics\Extensions.cs" />
144 144 <Compile Include="IComponentContainer.cs" />
145 145 <Compile Include="PromiseEventType.cs" />
146 146 <Compile Include="ComponentContainer.cs" />
147 147 <Compile Include="DisposablePool.cs" />
148 148 <Compile Include="ObjectPool.cs" />
149 149 <Compile Include="Parallels\AsyncQueue.cs" />
150 150 <Compile Include="PromiseT.cs" />
151 151 <Compile Include="IDeferred.cs" />
152 152 <Compile Include="IDeferredT.cs" />
153 <Compile Include="AbstractPromise.cs" />
154 153 <Compile Include="Promise.cs" />
155 154 <Compile Include="PromiseTransientException.cs" />
156 155 <Compile Include="Parallels\Signal.cs" />
157 156 <Compile Include="Parallels\SharedLock.cs" />
158 157 <Compile Include="Diagnostics\ILogWriter.cs" />
159 158 <Compile Include="Diagnostics\ListenerBase.cs" />
160 159 <Compile Include="Parallels\BlockingQueue.cs" />
161 160 <Compile Include="ICancelationToken.cs" />
161 <Compile Include="AbstractEvent.cs" />
162 <Compile Include="AbstractPromise.cs" />
163 <Compile Include="AbstractPromiseT.cs" />
164 <Compile Include="FuncTask.cs" />
165 <Compile Include="FuncTaskBase.cs" />
166 <Compile Include="FuncTaskT.cs" />
167 <Compile Include="ChainTask.cs" />
162 168 </ItemGroup>
163 169 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
164 170 <ItemGroup />
165 171 <ProjectExtensions>
166 172 <MonoDevelop>
167 173 <Properties>
168 174 <Policies>
169 175 <CSharpFormattingPolicy IndentSwitchBody="True" NamespaceBraceStyle="EndOfLine" ClassBraceStyle="EndOfLine" InterfaceBraceStyle="EndOfLine" StructBraceStyle="EndOfLine" EnumBraceStyle="EndOfLine" MethodBraceStyle="EndOfLine" ConstructorBraceStyle="EndOfLine" DestructorBraceStyle="EndOfLine" BeforeMethodDeclarationParentheses="False" BeforeMethodCallParentheses="False" BeforeConstructorDeclarationParentheses="False" NewLineBeforeConstructorInitializerColon="NewLine" NewLineAfterConstructorInitializerColon="SameLine" BeforeIndexerDeclarationBracket="False" BeforeDelegateDeclarationParentheses="False" NewParentheses="False" SpacesBeforeBrackets="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
170 176 <TextStylePolicy FileWidth="120" EolMarker="Unix" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
171 177 <DotNetNamingPolicy DirectoryNamespaceAssociation="PrefixedHierarchical" ResourceNamePolicy="MSBuild" />
172 178 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="application/xml" />
173 179 <XmlFormattingPolicy inheritsSet="Mono" inheritsScope="application/xml" scope="application/xml" />
174 180 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" />
175 181 <NameConventionPolicy>
176 182 <Rules>
177 183 <NamingRule Name="Namespaces" AffectedEntity="Namespace" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
178 184 <NamingRule Name="Types" AffectedEntity="Class, Struct, Enum, Delegate" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
179 185 <NamingRule Name="Interfaces" AffectedEntity="Interface" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
180 186 <RequiredPrefixes>
181 187 <String>I</String>
182 188 </RequiredPrefixes>
183 189 </NamingRule>
184 190 <NamingRule Name="Attributes" AffectedEntity="CustomAttributes" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
185 191 <RequiredSuffixes>
186 192 <String>Attribute</String>
187 193 </RequiredSuffixes>
188 194 </NamingRule>
189 195 <NamingRule Name="Event Arguments" AffectedEntity="CustomEventArgs" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
190 196 <RequiredSuffixes>
191 197 <String>EventArgs</String>
192 198 </RequiredSuffixes>
193 199 </NamingRule>
194 200 <NamingRule Name="Exceptions" AffectedEntity="CustomExceptions" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
195 201 <RequiredSuffixes>
196 202 <String>Exception</String>
197 203 </RequiredSuffixes>
198 204 </NamingRule>
199 205 <NamingRule Name="Methods" AffectedEntity="Methods" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
200 206 <NamingRule Name="Static Readonly Fields" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Protected, Public" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True" />
201 207 <NamingRule Name="Fields (Non Private)" AffectedEntity="Field" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
202 208 <NamingRule Name="ReadOnly Fields (Non Private)" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False" />
203 209 <NamingRule Name="Fields (Private)" AffectedEntity="Field, ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
204 210 <RequiredPrefixes>
205 211 <String>m_</String>
206 212 </RequiredPrefixes>
207 213 </NamingRule>
208 214 <NamingRule Name="Static Fields (Private)" AffectedEntity="Field" VisibilityMask="Private" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True">
209 215 <RequiredPrefixes>
210 216 <String>_</String>
211 217 </RequiredPrefixes>
212 218 </NamingRule>
213 219 <NamingRule Name="ReadOnly Fields (Private)" AffectedEntity="ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
214 220 <RequiredPrefixes>
215 221 <String>m_</String>
216 222 </RequiredPrefixes>
217 223 </NamingRule>
218 224 <NamingRule Name="Constant Fields" AffectedEntity="ConstantField" VisibilityMask="VisibilityMask" NamingStyle="AllUpper" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
219 225 <NamingRule Name="Properties" AffectedEntity="Property" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
220 226 <NamingRule Name="Events" AffectedEntity="Event" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
221 227 <NamingRule Name="Enum Members" AffectedEntity="EnumMember" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
222 228 <NamingRule Name="Parameters" AffectedEntity="Parameter, LocalVariable" VisibilityMask="VisibilityMask" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
223 229 <NamingRule Name="Type Parameters" AffectedEntity="TypeParameter" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
224 230 <RequiredPrefixes>
225 231 <String>T</String>
226 232 </RequiredPrefixes>
227 233 </NamingRule>
228 234 </Rules>
229 235 </NameConventionPolicy>
230 236 </Policies>
231 237 </Properties>
232 238 </MonoDevelop>
233 239 </ProjectExtensions>
234 240 </Project> No newline at end of file
@@ -1,222 +1,22
1 1 using System;
2 using System.Diagnostics;
2 using Implab.Parallels;
3 3
4 4 namespace Implab {
5 public class Promise : AbstractPromise<Promise.HandlerDescriptor>, IPromise, IDeferred {
6
7 public struct HandlerDescriptor {
8 readonly Action m_success;
9 readonly Action<Exception> m_error;
10 readonly Action<Exception> m_cancel;
11 readonly IDeferred m_deferred;
12
13 public HandlerDescriptor(Action success, Action<Exception> error, Action<Exception> cancel, IDeferred deferred) {
14 m_success = success;
15 m_error = error;
16 m_cancel = cancel;
17 m_deferred = deferred;
18 }
19
20 public void SignalSuccess() {
21 if (m_success != null) {
22 try {
23 m_success();
24 if (m_deferred != null)
25 m_deferred.Resolve();
26 } catch (Exception err) {
27 SignalError(err);
28 }
29 }
30 }
5 public class Promise : AbstractPromise, IDeferred {
6 public static readonly Promise SUCCESS;
31 7
32 public void SignalError(Exception err) {
33 if (m_error != null) {
34 try {
35 m_error(err);
36 if (m_deferred != null)
37 m_deferred.Resolve();
38 } catch (Exception err2) {
39 if (m_deferred != null)
40 m_deferred.Reject(err2);
41 }
42 } else {
43 if (m_deferred != null)
44 m_deferred.Reject(err);
45 }
46 }
47
48 public void SignalCancel(Exception reason) {
49 if (m_cancel != null) {
50 try {
51 m_cancel(reason);
52 if (m_deferred != null)
53 m_deferred.Resolve();
54 } catch (Exception err) {
55 SignalError(err);
56 }
57 } else if (reason != null && m_error != null) {
58 try {
59 m_error(new OperationCanceledException("The operation was canceled.", reason));
60 if (m_deferred != null)
61 m_deferred.Resolve();
62 } catch (Exception err) {
63 SignalError(err);
64 }
65 } else {
66 if (m_deferred != null)
67 m_deferred.Cancel(reason);
68 }
69 }
8 static Promise() {
9 SUCCESS = new Promise();
10 SUCCESS.Resolve();
70 11 }
71 12
72 13 public void Resolve() {
73 BeginSetResult();
74 EndSetResult();
14 SetResult();
75 15 }
76 16
77 17 public void Reject(Exception error) {
78 18 SetError(error);
79 19 }
80
81 #region implemented abstract members of AbstractPromise
82
83 protected override void SignalSuccess(HandlerDescriptor handler) {
84 handler.SignalSuccess();
85 }
86
87 protected override void SignalError(HandlerDescriptor handler, Exception error) {
88 handler.SignalError(error);
89 }
90
91 protected override void SignalCancelled(HandlerDescriptor handler, Exception reason) {
92 handler.SignalCancel(reason);
93 }
94
95 protected override void Listen(PromiseEventType events, Action handler) {
96 AddHandler(new HandlerDescriptor(
97 events.HasFlag(PromiseEventType.Success) ? handler : null,
98 events.HasFlag(PromiseEventType.Error) ? new Action<Exception>(err => handler()) : null,
99 events.HasFlag(PromiseEventType.Cancelled) ? new Action<Exception>(reason => handler()) : null,
100 null
101 ));
102 }
103
104 #endregion
105
106
107 public Type PromiseType {
108 get {
109 return typeof(void);
110 20 }
111 21 }
112 22
113 public IPromise Then(Action success, Action<Exception> error, Action<Exception> cancel) {
114 var promise = new Promise();
115 if (success != null)
116 promise.On(Cancel, PromiseEventType.Cancelled);
117
118 AddHandler(new HandlerDescriptor(success, error, cancel, promise));
119
120 return promise;
121 }
122
123 public IPromise Then(Action success, Action<Exception> error) {
124 return Then(success, error, null);
125 }
126
127 public IPromise Then(Action success) {
128 return Then(success, null, null);
129 }
130
131 public IPromise On(Action success, Action<Exception> error, Action<Exception> cancel) {
132 AddHandler(new HandlerDescriptor(success, error, cancel, null));
133 return this;
134 }
135
136 public IPromise On(Action success, Action<Exception> error) {
137 return On(success, error, null);
138 }
139
140 public IPromise On(Action success) {
141 return On(success, null, null);
142 }
143
144 public IPromise On(Action handler, PromiseEventType events) {
145 return On(
146 events.HasFlag(PromiseEventType.Success) ? handler : null,
147 events.HasFlag(PromiseEventType.Error) ? new Action<Exception>(err => handler()) : null,
148 events.HasFlag(PromiseEventType.Cancelled) ? new Action<Exception>(reason => handler()) : null
149 );
150 }
151
152 public IPromise<T> Cast<T>() {
153 throw new InvalidCastException();
154 }
155
156 public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<Exception,IPromise> cancel) {
157 var medium = new Promise();
158
159 On(
160 () => {
161 if (medium.IsCancelled)
162 return;
163 if (chained != null)
164 ConnectPromise(chained(), medium);
165 },
166 ex => {
167 if (medium.IsCancelled)
168 return;
169 if (error != null) {
170 try {
171 ConnectPromise(error(ex), medium);
172 } catch (Exception ex2) {
173 medium.Reject(ex2);
174 }
175 } else {
176 medium.Reject(ex);
177 }
178 },
179 reason => {
180 if (medium.IsCancelled)
181 return;
182 if (cancel != null)
183 ConnectPromise(cancel(reason), medium);
184 else
185 medium.Cancel(reason);
186 }
187 );
188
189 if (chained != null)
190 medium.On(Cancel, PromiseEventType.Cancelled);
191
192 return medium;
193 }
194
195 static void ConnectPromise(IPromise result, Promise medium) {
196 if (result != null) {
197 result.On(
198 medium.Resolve,
199 medium.Reject,
200 medium.Cancel
201 );
202 medium.On(null,null,result.Cancel);
203 } else {
204 medium.Reject(
205 new NullReferenceException(
206 "The chained asynchronous operation returned" +
207 " 'null' where the promise instance is expected"
208 )
209 );
210 }
211 }
212
213 public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error) {
214 return Chain(chained, error, null);
215 }
216
217 public IPromise Chain(Func<IPromise> chained) {
218 return Chain(chained, null, null);
219 }
220 }
221 }
222
This diff has been collapsed as it changes many lines, (533 lines changed) Show them Hide them
@@ -1,574 +1,63
1 1 using System;
2 2 using System.Diagnostics;
3 using Implab.Parallels;
3 4
4 5 namespace Implab {
5 6
6 7 /// <summary>
7 8 /// Класс для асинхронного получСния Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ². Π’Π°ΠΊ Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΠΎΠ΅ "ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅".
8 9 /// </summary>
9 10 /// <typeparam name="T">Π’ΠΈΠΏ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌΠΎΠ³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°</typeparam>
10 11 /// <remarks>
11 12 /// <para>БСрвис ΠΏΡ€ΠΈ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ ΠΊ Π΅Π³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρƒ Π΄Π°Π΅Ρ‚ ΠΎΠ±Π΅Ρ‰Π°ΠΈΠ½ΠΈΠ΅ ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ,
12 13 /// ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ² Ρ‚Π°ΠΊΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ряд ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹Ρ… Π²Ρ‹Π·ΠΎΠ²ΠΎ для получСния
13 14 /// событий выполнСния обСщания, Ρ‚ΠΎΠ΅ΡΡ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΈ прСдоставлСнии Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ².</para>
14 15 /// <para>
15 16 /// ΠžΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚Π°ΠΊ ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ с ошибкой. Для подписки Π½Π°
16 17 /// Π΄Π°Π½Π½Ρ‹Π΅ события ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Then</c>.
17 18 /// </para>
18 19 /// <para>
19 20 /// БСрвис, Π² свою ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ, ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ (Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ с ошибкой),
20 21 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Resolve</c> Π»ΠΈΠ±ΠΎ <c>Reject</c> для оповСщСния ΠΊΠ»ΠΈΠ΅Ρ‚Π½Π° ΠΎ
21 22 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ обСщания.
22 23 /// </para>
23 24 /// <para>
24 25 /// Если сСрвСр успСл Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΅Ρ‰Π΅ Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π½Π° Π½Π΅Π³ΠΎ подписался,
25 26 /// Ρ‚ΠΎ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ подписки ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΠ²ΡƒΡŽΡ‰ΠΈΠ΅ события Π² синхронном
26 27 /// Ρ€Π΅ΠΆΠΈΠΌΠ΅ ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΠΎΠ²Π΅Ρ‰Π΅Π½ Π² любом случаС. Π˜Π½Π°Ρ‡Π΅, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ΡΡ Π²
27 28 /// список Π² порядкС подписания ΠΈ Π² этом ΠΆΠ΅ порядкС ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ
28 29 /// обСщания.
29 30 /// </para>
30 31 /// <para>
31 32 /// ΠžΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ обСщания ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Π»ΠΈΠ±ΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ
32 33 /// связанныС асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ‚Π°ΠΊΠΆΠ΅ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ обСщания. Для этого слСдуСт
33 34 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ Ρ„ΠΎΡ€ΠΌΡƒ ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ <c>Then</c>.
34 35 /// </para>
35 36 /// <para>
36 37 /// Π’Π°ΠΊΠΆΠ΅ Ρ…ΠΎΡ€ΠΎΡˆΠΈΠΌ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎΠΌ являСтся Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ <c>Resolve</c> ΠΈ <c>Reject</c> Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ
37 38 /// Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€ обСщания ΠΈΠ½Π°Ρ‡Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ΡŒ противорСчия.
38 39 /// </para>
39 40 /// </remarks>
40 public class Promise<T> : AbstractPromise<IDeferred<T>>, IPromise<T>, IDeferred<T> {
41
42 class StubDeferred : IDeferred, IDeferred<T> {
43 public static readonly StubDeferred instance = new StubDeferred();
44
45 StubDeferred() {
46 }
47
48 #region IDeferred implementation
49
50 public void Resolve(T value) {
51 }
52
53 public void Resolve() {
54 }
55
56 public void Reject(Exception error) {
57 }
58
59 #endregion
60
61 #region ICancellable implementation
62
63 public void Cancel() {
64 }
65
66 public void Cancel(Exception reason) {
67 }
68
69 #endregion
70
71
72 }
73
74 class RemapDescriptor<T2> : IDeferred<T> {
75 readonly Func<T,T2> m_remap;
76 readonly Func<Exception, T2> m_failed;
77 readonly Func<Exception, T2> m_cancel;
78 readonly IDeferred<T2> m_deferred;
79
80 public RemapDescriptor(Func<T,T2> remap, Func<Exception,T2> failed, Func<Exception, T2> cancel, IDeferred<T2> deferred ) {
81 Debug.Assert(deferred != null);
82 m_remap = remap;
83 m_failed = failed;
84 m_cancel = cancel;
85 m_deferred = deferred;
86 }
87
88
89
90 #region IDeferred implementation
91
92 public void Resolve(T value) {
93 if (m_remap != null) {
94 try {
95 m_deferred.Resolve(m_remap(value));
96 } catch (Exception ex) {
97 Reject(ex);
98 }
99 }
100 }
41 public class Promise<T> : AbstractPromise<T>, IDeferred<T> {
101 42
102 public void Reject(Exception error) {
103 if (m_failed != null) {
104 try {
105 m_deferred.Resolve(m_failed(error));
106 } catch (Exception ex) {
107 m_deferred.Reject(ex);
108 }
109 } else {
110 m_deferred.Reject(error);
111 }
112 }
113
114
115 #endregion
116
117 #region ICancellable implementation
118
119 public void Cancel(Exception reason) {
120 if (m_cancel != null) {
121 try {
122 m_deferred.Resolve(m_cancel(reason));
123 } catch (Exception ex) {
124 Reject(ex);
125 }
126 } else {
127 m_deferred.Cancel(reason);
128 }
129 }
130
131 public void Cancel() {
132 Cancel(null);
133 }
134 #endregion
135 }
136
137 class ListenerDescriptor : IDeferred<T> {
138 readonly Action m_handler;
139 readonly PromiseEventType m_events;
140
141 public ListenerDescriptor(Action handler, PromiseEventType events) {
142 Debug.Assert(handler != null);
143
144 m_handler = handler;
145 m_events = events;
146 }
147
148 #region IDeferred implementation
149
150 public void Resolve(T value) {
151 if (m_events.HasFlag(PromiseEventType.Success)) {
152 try {
153 m_handler();
154 // Analysis disable once EmptyGeneralCatchClause
155 } catch {
156 }
157 }
158 }
159
160 public void Reject(Exception error) {
161 if (m_events.HasFlag(PromiseEventType.Error)){
162 try {
163 m_handler();
164 // Analysis disable once EmptyGeneralCatchClause
165 } catch {
166 }
167 }
168 }
169
170 #endregion
171
172 #region ICancellable implementation
173
174 public void Cancel() {
175 Cancel(null);
43 public static IPromise<T> FromResult(T value) {
44 var p = new Promise<T>();
45 p.Resolve(value);
46 return p;
176 47 }
177 48
178 public void Cancel(Exception reason) {
179 if (m_events.HasFlag(PromiseEventType.Cancelled)){
180 try {
181 m_handler();
182 // Analysis disable once EmptyGeneralCatchClause
183 } catch {
184 }
185 }
186 }
187
188 #endregion
189 }
190
191 class ValueEventDescriptor : IDeferred<T> {
192 readonly Action<T> m_success;
193 readonly Action<Exception> m_failed;
194 readonly Action<Exception> m_cancelled;
195 readonly IDeferred<T> m_deferred;
196
197 public ValueEventDescriptor(Action<T> success, Action<Exception> failed, Action<Exception> cancelled, IDeferred<T> deferred) {
198 Debug.Assert(deferred != null);
199
200 m_success = success;
201 m_failed = failed;
202 m_cancelled = cancelled;
203 m_deferred = deferred;
204 }
205
206 #region IDeferred implementation
207
208 public void Resolve(T value) {
209 if (m_success != null) {
210 try {
211 m_success(value);
212 m_deferred.Resolve(value);
213 } catch (Exception ex) {
214 Reject(ex);
215 }
216 }
217 }
218
219 public void Reject(Exception error) {
220 if (m_failed != null) {
221 try {
222 m_failed(error);
223 m_deferred.Resolve(default(T));
224 } catch(Exception ex) {
225 m_deferred.Reject(ex);
226 }
227 } else {
228 m_deferred.Reject(error);
229 }
230 }
231
232 #endregion
233
234 #region ICancellable implementation
235
236 public void Cancel(Exception reason) {
237 if (m_cancelled != null) {
238 try {
239 m_cancelled(reason);
240 m_deferred.Resolve(default(T));
241 } catch (Exception ex) {
242 Reject(ex);
243 }
244 } else {
245 m_deferred.Cancel(reason);
246 }
247 }
248
249 public void Cancel() {
250 Cancel(null);
49 public static IPromise<T> FromException(Exception error) {
50 var p = new Promise<T>();
51 p.Reject(error);
52 return p;
251 53 }
252 54
253 #endregion
254 }
255
256 public class EventDescriptor : IDeferred<T> {
257 readonly Action m_success;
258 readonly Action<Exception> m_failed;
259 readonly Action<Exception> m_cancelled;
260 readonly IDeferred m_deferred;
261
262 public EventDescriptor(Action success, Action<Exception> failed, Action<Exception> cancelled, IDeferred deferred) {
263 Debug.Assert(deferred != null);
264
265 m_success = success;
266 m_failed = failed;
267 m_cancelled = cancelled;
268 m_deferred = deferred;
269 }
270
271 #region IDeferred implementation
272
273 public void Resolve(T value) {
274 if (m_success != null) {
275 try {
276 m_success();
277 m_deferred.Resolve();
278 } catch (Exception ex) {
279 Reject(ex);
280 }
281 }
282 }
283
284 public void Reject(Exception error) {
285 if (m_failed != null) {
286 try {
287 m_failed(error);
288 m_deferred.Resolve();
289 } catch (Exception ex) {
290 m_deferred.Reject(ex);
291 }
292 } else {
293 m_deferred.Reject(error);
294 }
295 }
296
297 #endregion
298
299 #region ICancellable implementation
300
301 public void Cancel(Exception reason) {
302 if (m_cancelled != null) {
303 try {
304 m_cancelled(reason);
305 m_deferred.Resolve();
306 } catch (Exception ex) {
307 Reject(ex);
308 }
309 } else {
310 m_deferred.Cancel(reason);
311 }
312 }
313
314 public void Cancel() {
315 Cancel(null);
316 }
317
318 #endregion
319 }
320
321 T m_result;
322
323 55 public virtual void Resolve(T value) {
324 if (BeginSetResult()) {
325 m_result = value;
326 EndSetResult();
327 }
56 SetResult(value);
328 57 }
329 58
330 59 public void Reject(Exception error) {
331 60 SetError(error);
332 61 }
333
334 public Type PromiseType {
335 get {
336 return typeof(T);
337 }
338 }
339
340 public new T Join() {
341 WaitResult(-1);
342 return m_result;
343 }
344 public new T Join(int timeout) {
345 WaitResult(timeout);
346 return m_result;
347 }
348
349 public IPromise<T> On(Action<T> success, Action<Exception> error, Action<Exception> cancel) {
350 AddHandler(new ValueEventDescriptor(success, error, cancel, StubDeferred.instance));
351 return this;
352 }
353
354 public IPromise<T> On(Action<T> success, Action<Exception> error) {
355 AddHandler(new ValueEventDescriptor(success, error, null, StubDeferred.instance));
356 return this;
357 }
358
359 public IPromise<T> On(Action<T> success) {
360 AddHandler(new ValueEventDescriptor(success, null, null, StubDeferred.instance));
361 return this;
362 }
363
364 public IPromise<T> On(Action handler, PromiseEventType events) {
365 Listen(events, handler);
366 return this;
367 }
368
369 public IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error, Func<Exception, T2> cancel) {
370 var promise = new Promise<T2>();
371 if (mapper != null)
372 promise.On((Action)null, null, Cancel);
373 AddHandler(new RemapDescriptor<T2>(mapper, error, cancel, promise));
374 return promise;
375 }
376
377 public IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error) {
378 var promise = new Promise<T2>();
379 if (mapper != null)
380 promise.On((Action)null, null, Cancel);
381 AddHandler(new RemapDescriptor<T2>(mapper, error, null, promise));
382 return promise;
383 }
384
385 public IPromise<T2> Then<T2>(Func<T, T2> mapper) {
386 var promise = new Promise<T2>();
387 if (mapper != null)
388 promise.On((Action)null, null, Cancel);
389 AddHandler(new RemapDescriptor<T2>(mapper, null, null, promise));
390 return promise;
391 }
392
393 public IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception, IPromise<T2>> error, Func<Exception, IPromise<T2>> cancel) {
394 // this promise will be resolved when an asyc operation is started
395 var promise = new Promise<IPromise<T2>>();
396
397 AddHandler(new RemapDescriptor<IPromise<T2>>(
398 chained,
399 error,
400 cancel,
401 promise
402 ));
403
404 var medium = new Promise<T2>();
405
406 if (chained != null)
407 medium.On(Cancel, PromiseEventType.Cancelled);
408
409 // we need to connect started async operation with the medium
410 // if the async operation hasn't been started by the some reason
411 // report is to the medium
412 promise.On(
413 result => ConnectPromise<T2>(result, medium),
414 medium.Reject,
415 medium.Cancel
416 );
417
418 return medium;
419 }
420
421 static void ConnectPromise<T2>(IPromise<T2> result, Promise<T2> medium) {
422 if (result != null) {
423 result.On(
424 medium.Resolve,
425 medium.Reject,
426 medium.Cancel
427 );
428 medium.On(result.Cancel, PromiseEventType.Cancelled);
429 } else {
430 medium.Reject(
431 new NullReferenceException(
432 "The chained asynchronous operation returned" +
433 " 'null' where the promise instance is expected"
434 )
435 );
436 62 }
437 63 }
438
439 public IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception, IPromise<T2>> error) {
440 return Chain(chained, error, null);
441 }
442
443 public IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained) {
444 return Chain(chained, null, null);
445 }
446
447 public IPromise Then(Action success, Action<Exception> error, Action<Exception> cancel) {
448 var promise = new Promise();
449 if (success != null)
450 promise.On(null, null, Cancel);
451
452 AddHandler(new EventDescriptor(success, error, cancel, promise));
453
454 return promise;
455 }
456
457 public IPromise Then(Action success, Action<Exception> error) {
458 return Then(success, error, null);
459 }
460
461 public IPromise Then(Action success) {
462 return Then(success, null, null);
463 }
464
465 public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<Exception, IPromise> cancel) {
466 var promise = new Promise<IPromise>();
467
468 AddHandler(
469 new RemapDescriptor<IPromise>(
470 x => chained(),
471 error,
472 cancel,
473 promise
474 )
475 );
476
477 var medium = new Promise();
478 if (chained != null)
479 medium.On(null, null, Cancel);
480
481 promise.On(
482 result => ConnectPromise(result, medium),
483 medium.Reject,
484 medium.Cancel
485 );
486
487 return medium;
488 }
489
490 static void ConnectPromise(IPromise result, Promise medium) {
491 if (result != null) {
492 result.On(
493 medium.Resolve,
494 medium.Reject,
495 medium.Cancel
496 );
497 medium.On(null, null, result.Cancel);
498 } else {
499 medium.Reject(
500 new NullReferenceException(
501 "The chained asynchronous operation returned" +
502 " 'null' where the promise instance is expected"
503 )
504 );
505 }
506 }
507
508 public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error) {
509 return Chain(chained, error, null);
510 }
511
512 public IPromise Chain(Func<IPromise> chained) {
513 return Chain(chained, null, null);
514 }
515
516 public IPromise On(Action success, Action<Exception> error, Action<Exception> cancel) {
517 AddHandler(new EventDescriptor(success,error,cancel, StubDeferred.instance));
518 return this;
519 }
520
521 public IPromise On(Action success, Action<Exception> error) {
522 AddHandler(new EventDescriptor(success, error, null, StubDeferred.instance));
523 return this;
524 }
525
526 public IPromise On(Action success) {
527 Listen(PromiseEventType.Success, success);
528 return this;
529 }
530
531 IPromise IPromise.On(Action handler, PromiseEventType events) {
532 Listen(events,handler);
533 return this;
534 }
535
536 public IPromise<T2> Cast<T2>() {
537 return (IPromise<T2>)this;
538 }
539
540 #region implemented abstract members of AbstractPromise
541
542 protected override void SignalSuccess(IDeferred<T> handler) {
543 handler.Resolve(m_result);
544 }
545
546 protected override void SignalError(IDeferred<T> handler, Exception error) {
547 handler.Reject(error);
548 }
549
550 protected override void SignalCancelled(IDeferred<T> handler, Exception reason) {
551 handler.Cancel(reason);
552 }
553
554 protected override void Listen(PromiseEventType events, Action handler) {
555 if (handler != null)
556 AddHandler(new ListenerDescriptor(handler, events));
557 }
558
559 #endregion
560
561 public static IPromise<T> ResultToPromise(T value) {
562 var p = new Promise<T>();
563 p.Resolve(value);
564 return p;
565 }
566
567 public static IPromise<T> ExceptionToPromise(Exception error) {
568 var p = new Promise<T>();
569 p.Reject(error);
570 return p;
571 }
572
573 }
574 }
General Comments 0
You need to be logged in to leave comments. Login now