Mercurial > pub > ImplabNet
comparison Implab/Promise.cs @ 9:c82e0dfbb4dd promises
sync
author | cin |
---|---|
date | Sat, 02 Nov 2013 00:55:47 +0400 |
parents | 7ea9363fef6c |
children | aa33d0bb8c0c |
comparison
equal
deleted
inserted
replaced
8:849075f49d5c | 9:c82e0dfbb4dd |
---|---|
46 /// <para> | 46 /// <para> |
47 /// Также хорошим правилом является то, что <c>Resolve</c> и <c>Reject</c> должен вызывать | 47 /// Также хорошим правилом является то, что <c>Resolve</c> и <c>Reject</c> должен вызывать |
48 /// только инициатор обещания иначе могут возникнуть противоречия. | 48 /// только инициатор обещания иначе могут возникнуть противоречия. |
49 /// </para> | 49 /// </para> |
50 /// </remarks> | 50 /// </remarks> |
51 public class Promise<T>: IPromise { | 51 public class Promise<T> : IPromise { |
52 | 52 |
53 struct ResultHandlerInfo { | 53 struct ResultHandlerInfo { |
54 public ResultHandler<T> resultHandler; | 54 public ResultHandler<T> resultHandler; |
55 public ErrorHandler errorHandler; | 55 public ErrorHandler errorHandler; |
56 public Action cancelHandler; | 56 } |
57 } | 57 |
58 | 58 IPromise m_parent; |
59 LinkedList<ResultHandlerInfo> m_handlersChain = new LinkedList<ResultHandlerInfo>(); | 59 |
60 LinkedList<ResultHandlerInfo> m_resultHandlers = new LinkedList<ResultHandlerInfo>(); | |
61 LinkedList<Action> m_cancelHandlers = new LinkedList<Action>(); | |
62 | |
63 object m_lock = new Object(); | |
64 bool m_cancellable; | |
65 | |
60 PromiseState m_state; | 66 PromiseState m_state; |
61 bool m_cancellable; | |
62 T m_result; | 67 T m_result; |
63 Exception m_error; | 68 Exception m_error; |
64 IPromise m_parent; | 69 |
65 int m_childrenCount; | 70 int m_childrenCount; |
66 | 71 |
67 public Promise() { | 72 public Promise() { |
68 m_cancellable = true; | 73 m_cancellable = true; |
69 } | 74 } |
70 | 75 |
71 public Promise(IPromise parent, bool cancellable) | 76 public Promise(IPromise parent, bool cancellable) { |
72 { | |
73 m_cancellable = cancellable; | 77 m_cancellable = cancellable; |
74 m_parent = parent; | 78 m_parent = parent; |
75 } | 79 } |
76 | 80 |
77 /// <summary> | 81 /// <summary> |
95 throw new InvalidOperationException("The promise is already resolved"); | 99 throw new InvalidOperationException("The promise is already resolved"); |
96 m_result = result; | 100 m_result = result; |
97 m_state = PromiseState.Resolved; | 101 m_state = PromiseState.Resolved; |
98 } | 102 } |
99 | 103 |
100 ResultHandlerInfo handler; | 104 // state has been changed to rejected new handlers can't be added |
105 | |
106 foreach (var handler in m_resultHandlers) | |
107 InvokeHandler(handler); | |
108 | |
109 /* ResultHandlerInfo handler; | |
101 while (FetchNextHandler(out handler)) | 110 while (FetchNextHandler(out handler)) |
102 InvokeHandler(handler); | 111 InvokeHandler(handler); */ |
103 } | 112 } |
104 | 113 |
105 /// <summary> | 114 /// <summary> |
106 /// Выполняет обещание, сообщая об ошибке | 115 /// Выполняет обещание, сообщая об ошибке |
107 /// </summary> | 116 /// </summary> |
115 throw new InvalidOperationException("The promise is already resolved"); | 124 throw new InvalidOperationException("The promise is already resolved"); |
116 m_error = error; | 125 m_error = error; |
117 m_state = PromiseState.Rejected; | 126 m_state = PromiseState.Rejected; |
118 } | 127 } |
119 | 128 |
120 ResultHandlerInfo handler; | 129 // state has been changed to rejected new handlers can't be added |
130 | |
131 foreach (var handler in m_resultHandlers) | |
132 InvokeHandler(handler); | |
133 | |
134 /*ResultHandlerInfo handler; | |
121 while (FetchNextHandler(out handler)) | 135 while (FetchNextHandler(out handler)) |
122 InvokeHandler(handler); | 136 InvokeHandler(handler);*/ |
123 } | 137 } |
124 | 138 |
125 /// <summary> | 139 /// <summary> |
126 /// Отменяет операцию, если это возможно. | 140 /// Отменяет операцию, если это возможно. |
127 /// </summary> | 141 /// </summary> |
128 /// <returns><c>true</c> Операция была отменена, обработчики не будут вызваны.<c>false</c> отмена не возможна, поскольку обещание уже выполнено и обработчики отработали.</returns> | 142 /// <returns><c>true</c> Операция была отменена, обработчики не будут вызваны.<c>false</c> отмена не возможна, поскольку обещание уже выполнено и обработчики отработали.</returns> |
129 public bool Cancel() { | 143 public bool Cancel() { |
130 lock (this) { | 144 return Cancel(true); |
131 if (m_state == PromiseState.Unresolved && m_cancellable) | |
132 { | |
133 m_state = PromiseState.Cancelled; | |
134 EventHandler temp = Cancelled; | |
135 | |
136 if (temp != null) | |
137 temp(this, new EventArgs()); | |
138 | |
139 return true; | |
140 } else | |
141 return false; | |
142 } | |
143 } | 145 } |
144 | 146 |
145 /// <summary> | 147 /// <summary> |
146 /// Добавляет обработчики событий выполнения обещания. | 148 /// Добавляет обработчики событий выполнения обещания. |
147 /// </summary> | 149 /// </summary> |
351 handler = default(ResultHandlerInfo); | 353 handler = default(ResultHandlerInfo); |
352 | 354 |
353 lock (this) { | 355 lock (this) { |
354 Debug.Assert(m_state != PromiseState.Unresolved); | 356 Debug.Assert(m_state != PromiseState.Unresolved); |
355 | 357 |
356 if (m_handlersChain.Count > 0) { | 358 if (m_resultHandlers.Count > 0) { |
357 handler = m_handlersChain.First.Value; | 359 handler = m_resultHandlers.First.Value; |
358 m_handlersChain.RemoveFirst(); | 360 m_resultHandlers.RemoveFirst(); |
359 return true; | 361 return true; |
360 } else { | 362 } else { |
361 return false; | 363 return false; |
362 } | 364 } |
363 } | 365 } |
366 void AddHandler(ResultHandlerInfo handler) { | 368 void AddHandler(ResultHandlerInfo handler) { |
367 bool invokeRequired = false; | 369 bool invokeRequired = false; |
368 | 370 |
369 lock (this) { | 371 lock (this) { |
370 if (m_state == PromiseState.Unresolved) | 372 if (m_state == PromiseState.Unresolved) |
371 m_handlersChain.AddLast(handler); | 373 m_resultHandlers.AddLast(handler); |
372 else | 374 else |
373 invokeRequired = true; | 375 invokeRequired = true; |
374 } | 376 } |
375 | 377 |
376 // обработчики не должны блокировать сам объект | 378 // обработчики не должны блокировать сам объект |
393 } catch { } | 395 } catch { } |
394 } | 396 } |
395 } | 397 } |
396 | 398 |
397 | 399 |
400 | |
401 public bool IsExclusive { | |
402 get { | |
403 lock (m_lock) { | |
404 return m_childrenCount <= 1; | |
405 } | |
406 } | |
407 } | |
408 | |
409 public PromiseState State { | |
410 get { | |
411 lock (m_lock) { | |
412 return m_state; | |
413 } | |
414 } | |
415 } | |
416 | |
417 public bool Cancel(bool dependencies) { | |
418 bool result; | |
419 | |
420 lock (m_lock) { | |
421 if (m_state == PromiseState.Unresolved) { | |
422 m_state = PromiseState.Cancelled; | |
423 result = true; | |
424 } else { | |
425 result = false; | |
426 } | |
427 } | |
428 | |
429 if (dependencies && m_parent != null && m_parent.IsExclusive) { | |
430 // TODO syncronize IsExclusive, AddHandler, Cancel (maybe CancelExclusive) | |
431 m_parent.Cancel(true); | |
432 } | |
433 | |
434 if (result) { | |
435 // state has been changed to cancelled, new handlers can't be added | |
436 foreach (var handler in m_cancelHandlers) | |
437 handler(); | |
438 } | |
439 | |
440 return result; | |
441 } | |
398 } | 442 } |
399 } | 443 } |