Mercurial > pub > ImplabNet
comparison Implab/Promise.cs @ 7:7ea9363fef6c promises
inital progress handling
| author | cin |
|---|---|
| date | Fri, 01 Nov 2013 16:03:08 +0400 |
| parents | dfa21d507bc5 |
| children | c82e0dfbb4dd |
comparison
equal
deleted
inserted
replaced
| 6:dfa21d507bc5 | 7:7ea9363fef6c |
|---|---|
| 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> { | 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 } | 56 public Action cancelHandler; |
| 57 | |
| 58 enum State { | |
| 59 Unresolved, | |
| 60 Resolving, | |
| 61 Resolved, | |
| 62 Cancelled | |
| 63 } | 57 } |
| 64 | 58 |
| 65 LinkedList<ResultHandlerInfo> m_handlersChain = new LinkedList<ResultHandlerInfo>(); | 59 LinkedList<ResultHandlerInfo> m_handlersChain = new LinkedList<ResultHandlerInfo>(); |
| 66 State m_state; | 60 PromiseState m_state; |
| 67 bool m_cancellable; | 61 bool m_cancellable; |
| 68 T m_result; | 62 T m_result; |
| 69 Exception m_error; | 63 Exception m_error; |
| 64 IPromise m_parent; | |
| 65 int m_childrenCount; | |
| 70 | 66 |
| 71 public Promise() { | 67 public Promise() { |
| 72 m_cancellable = true; | 68 m_cancellable = true; |
| 69 } | |
| 70 | |
| 71 public Promise(IPromise parent, bool cancellable) | |
| 72 { | |
| 73 m_cancellable = cancellable; | |
| 74 m_parent = parent; | |
| 73 } | 75 } |
| 74 | 76 |
| 75 /// <summary> | 77 /// <summary> |
| 76 /// Событие, возникающее при отмене асинхронной операции. | 78 /// Событие, возникающее при отмене асинхронной операции. |
| 77 /// </summary> | 79 /// </summary> |
| 85 /// </summary> | 87 /// </summary> |
| 86 /// <param name="result">Результат выполнения.</param> | 88 /// <param name="result">Результат выполнения.</param> |
| 87 /// <exception cref="InvalidOperationException">Данное обещание уже выполнено</exception> | 89 /// <exception cref="InvalidOperationException">Данное обещание уже выполнено</exception> |
| 88 public void Resolve(T result) { | 90 public void Resolve(T result) { |
| 89 lock (this) { | 91 lock (this) { |
| 90 if (m_state == State.Cancelled) | 92 if (m_state == PromiseState.Cancelled) |
| 91 return; | 93 return; |
| 92 if (m_state != State.Unresolved) | 94 if (m_state != PromiseState.Unresolved) |
| 93 throw new InvalidOperationException("The promise is already resolved"); | 95 throw new InvalidOperationException("The promise is already resolved"); |
| 94 m_result = result; | 96 m_result = result; |
| 95 m_state = State.Resolving; | 97 m_state = PromiseState.Resolved; |
| 96 } | 98 } |
| 97 | 99 |
| 98 ResultHandlerInfo handler; | 100 ResultHandlerInfo handler; |
| 99 while (FetchNextHandler(out handler)) | 101 while (FetchNextHandler(out handler)) |
| 100 InvokeHandler(handler); | 102 InvokeHandler(handler); |
| 105 /// </summary> | 107 /// </summary> |
| 106 /// <param name="error">Исключение возникшее при выполнении операции</param> | 108 /// <param name="error">Исключение возникшее при выполнении операции</param> |
| 107 /// <exception cref="InvalidOperationException">Данное обещание уже выполнено</exception> | 109 /// <exception cref="InvalidOperationException">Данное обещание уже выполнено</exception> |
| 108 public void Reject(Exception error) { | 110 public void Reject(Exception error) { |
| 109 lock (this) { | 111 lock (this) { |
| 110 if (m_state == State.Cancelled) | 112 if (m_state == PromiseState.Cancelled) |
| 111 return; | 113 return; |
| 112 if (m_state != State.Unresolved) | 114 if (m_state != PromiseState.Unresolved) |
| 113 throw new InvalidOperationException("The promise is already resolved"); | 115 throw new InvalidOperationException("The promise is already resolved"); |
| 114 m_error = error; | 116 m_error = error; |
| 115 m_state = State.Resolving; | 117 m_state = PromiseState.Rejected; |
| 116 } | 118 } |
| 117 | 119 |
| 118 ResultHandlerInfo handler; | 120 ResultHandlerInfo handler; |
| 119 while (FetchNextHandler(out handler)) | 121 while (FetchNextHandler(out handler)) |
| 120 InvokeHandler(handler); | 122 InvokeHandler(handler); |
| 124 /// Отменяет операцию, если это возможно. | 126 /// Отменяет операцию, если это возможно. |
| 125 /// </summary> | 127 /// </summary> |
| 126 /// <returns><c>true</c> Операция была отменена, обработчики не будут вызваны.<c>false</c> отмена не возможна, поскольку обещание уже выполнено и обработчики отработали.</returns> | 128 /// <returns><c>true</c> Операция была отменена, обработчики не будут вызваны.<c>false</c> отмена не возможна, поскольку обещание уже выполнено и обработчики отработали.</returns> |
| 127 public bool Cancel() { | 129 public bool Cancel() { |
| 128 lock (this) { | 130 lock (this) { |
| 129 if (m_state == State.Unresolved && m_cancellable) { | 131 if (m_state == PromiseState.Unresolved && m_cancellable) |
| 130 m_state = State.Cancelled; | 132 { |
| 133 m_state = PromiseState.Cancelled; | |
| 131 EventHandler temp = Cancelled; | 134 EventHandler temp = Cancelled; |
| 132 | 135 |
| 133 if (temp != null) | 136 if (temp != null) |
| 134 temp(this, new EventArgs()); | 137 temp(this, new EventArgs()); |
| 135 | 138 |
| 346 /// <returns>Признак того, что еще остались обработчики в очереди</returns> | 349 /// <returns>Признак того, что еще остались обработчики в очереди</returns> |
| 347 bool FetchNextHandler(out ResultHandlerInfo handler) { | 350 bool FetchNextHandler(out ResultHandlerInfo handler) { |
| 348 handler = default(ResultHandlerInfo); | 351 handler = default(ResultHandlerInfo); |
| 349 | 352 |
| 350 lock (this) { | 353 lock (this) { |
| 351 Debug.Assert(m_state == State.Resolving); | 354 Debug.Assert(m_state != PromiseState.Unresolved); |
| 352 | 355 |
| 353 if (m_handlersChain.Count > 0) { | 356 if (m_handlersChain.Count > 0) { |
| 354 handler = m_handlersChain.First.Value; | 357 handler = m_handlersChain.First.Value; |
| 355 m_handlersChain.RemoveFirst(); | 358 m_handlersChain.RemoveFirst(); |
| 356 return true; | 359 return true; |
| 357 } else { | 360 } else { |
| 358 m_state = State.Resolved; | |
| 359 return false; | 361 return false; |
| 360 } | 362 } |
| 361 } | 363 } |
| 362 } | 364 } |
| 363 | 365 |
| 364 void AddHandler(ResultHandlerInfo handler) { | 366 void AddHandler(ResultHandlerInfo handler) { |
| 365 bool invokeRequired = false; | 367 bool invokeRequired = false; |
| 366 | 368 |
| 367 lock (this) { | 369 lock (this) { |
| 368 if (m_state != State.Resolved) | 370 if (m_state == PromiseState.Unresolved) |
| 369 m_handlersChain.AddLast(handler); | 371 m_handlersChain.AddLast(handler); |
| 370 else | 372 else |
| 371 invokeRequired = true; | 373 invokeRequired = true; |
| 372 } | 374 } |
| 373 | 375 |
