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