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 } |
