annotate Implab/Promise.cs @ 75:4439140706d0 v2

major refactoring, added tasks support
author cin
date Wed, 10 Sep 2014 11:17:37 +0400
parents c4140283575c
children c761fc982e1d
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2
aa367305156b small fixes
cin
parents: 1
diff changeset
1 using System;
aa367305156b small fixes
cin
parents: 1
diff changeset
2 using System.Collections.Generic;
aa367305156b small fixes
cin
parents: 1
diff changeset
3 using System.Reflection;
aa367305156b small fixes
cin
parents: 1
diff changeset
4 using System.Diagnostics;
aa367305156b small fixes
cin
parents: 1
diff changeset
5 using System.Threading;
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
6 using Implab.Parallels;
2
aa367305156b small fixes
cin
parents: 1
diff changeset
7
aa367305156b small fixes
cin
parents: 1
diff changeset
8 namespace Implab {
aa367305156b small fixes
cin
parents: 1
diff changeset
9
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
10 public delegate void ErrorHandler(Exception e);
11
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
11 public delegate T ErrorHandler<out T>(Exception e);
10
aa33d0bb8c0c implemeted new cancellable promises concept
cin
parents: 9
diff changeset
12 public delegate void ResultHandler<in T>(T result);
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
13 public delegate TNew ResultMapper<in TSrc,out TNew>(TSrc result);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
14 public delegate IPromise<TNew> ChainedOperation<in TSrc,TNew>(TSrc result);
2
aa367305156b small fixes
cin
parents: 1
diff changeset
15
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
16 /// <summary>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
17 /// Класс для асинхронного получения результатов. Так называемое "обещание".
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
18 /// </summary>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
19 /// <typeparam name="T">Тип получаемого результата</typeparam>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
20 /// <remarks>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
21 /// <para>Сервис при обращении к его методу дает обещаиние о выполнении операции,
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
22 /// клиент получив такое обещание может установить ряд обратных вызово для получения
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
23 /// событий выполнения обещания, тоесть завершения операции и предоставлении результатов.</para>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
24 /// <para>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
25 /// Обещение может быть как выполнено, так и выполнено с ошибкой. Для подписки на
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
26 /// данные события клиент должен использовать методы <c>Then</c>.
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
27 /// </para>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
28 /// <para>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
29 /// Сервис, в свою очередь, по окончанию выполнения операции (возможно с ошибкой),
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
30 /// использует методы <c>Resolve</c> либо <c>Reject</c> для оповещения клиетна о
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
31 /// выполнении обещания.
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
32 /// </para>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
33 /// <para>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
34 /// Если сервер успел выполнить обещание еще до того, как клиент на него подписался,
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
35 /// то в момент подписки клиента будут вызваны соответсвующие события в синхронном
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
36 /// режиме и клиент будет оповещен в любом случае. Иначе, обработчики добавляются в
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
37 /// список в порядке подписания и в этом же порядке они будут вызваны при выполнении
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
38 /// обещания.
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
39 /// </para>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
40 /// <para>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
41 /// Обрабатывая результаты обещания можно преобразовывать результаты либо инициировать
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
42 /// связанные асинхронные операции, которые также возвращают обещания. Для этого следует
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
43 /// использовать соответствующую форму методе <c>Then</c>.
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
44 /// </para>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
45 /// <para>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
46 /// Также хорошим правилом является то, что <c>Resolve</c> и <c>Reject</c> должен вызывать
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
47 /// только инициатор обещания иначе могут возникнуть противоречия.
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
48 /// </para>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
49 /// </remarks>
25
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
50 public class Promise<T> : IPromise<T> {
2
aa367305156b small fixes
cin
parents: 1
diff changeset
51
28
cin
parents: 27
diff changeset
52 protected struct HandlerDescriptor {
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
53 public ResultHandler<T> resultHandler;
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
54 public ErrorHandler<T> errorHandler;
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
55 public Action cancellHandler;
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
56 public Promise<T> medium;
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
57
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
58 public void Resolve(T result) {
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
59 if (resultHandler != null) {
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
60 try {
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
61 resultHandler(result);
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
62 } catch (Exception e) {
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
63 Reject(e);
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
64 return;
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
65 }
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
66 }
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
67 if (medium != null)
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
68 medium.Resolve(result);
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
69 }
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
70
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
71 public void Reject(Exception err) {
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
72 if (errorHandler != null) {
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
73 try {
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
74 var res = errorHandler(err);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
75 if (medium != null)
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
76 medium.Resolve(res);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
77 } catch (TransientPromiseException err2) {
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
78 if (medium != null)
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
79 medium.Reject(err2.InnerException);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
80 } catch (Exception err2) {
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
81 if (medium != null)
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
82 medium.Reject(err2);
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
83 }
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
84 } else if (medium != null)
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
85 medium.Reject(err);
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
86 }
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
87
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
88 public void Cancel() {
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
89 if (cancellHandler != null) {
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
90 try {
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
91 cancellHandler();
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
92 } catch (Exception err) {
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
93 Reject(err);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
94 return;
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
95 }
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
96 }
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
97 if (medium != null)
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
98 medium.Cancel();
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
99 }
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
100 }
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
101
71
1714fd8678ef code cleanup
cin
parents: 66
diff changeset
102 const int UNRESOLVED_SATE = 0;
1714fd8678ef code cleanup
cin
parents: 66
diff changeset
103 const int TRANSITIONAL_STATE = 1;
1714fd8678ef code cleanup
cin
parents: 66
diff changeset
104 const int SUCCEEDED_STATE = 2;
1714fd8678ef code cleanup
cin
parents: 66
diff changeset
105 const int REJECTED_STATE = 3;
1714fd8678ef code cleanup
cin
parents: 66
diff changeset
106 const int CANCELLED_STATE = 4;
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
107
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
108 readonly bool m_cancellable;
9
cin
parents: 7
diff changeset
109
10
aa33d0bb8c0c implemeted new cancellable promises concept
cin
parents: 9
diff changeset
110 int m_childrenCount = 0;
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
111 int m_state;
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
112 T m_result;
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
113 Exception m_error;
9
cin
parents: 7
diff changeset
114
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
115 readonly MTQueue<HandlerDescriptor> m_handlers = new MTQueue<HandlerDescriptor>();
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
116
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
117 public Promise() {
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
118 m_cancellable = true;
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
119 }
2
aa367305156b small fixes
cin
parents: 1
diff changeset
120
66
790e8a997d30 Refactoring
cin
parents: 65
diff changeset
121 public Promise(IPromise parent, bool cancellable) {
7
7ea9363fef6c inital progress handling
cin
parents: 6
diff changeset
122 m_cancellable = cancellable;
33
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
123 if (parent != null)
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
124 Cancelled(() => {
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
125 if (parent.IsExclusive)
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
126 parent.Cancel();
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
127 });
10
aa33d0bb8c0c implemeted new cancellable promises concept
cin
parents: 9
diff changeset
128 }
2
aa367305156b small fixes
cin
parents: 1
diff changeset
129
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
130 bool BeginTransit() {
71
1714fd8678ef code cleanup
cin
parents: 66
diff changeset
131 return UNRESOLVED_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, UNRESOLVED_SATE);
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
132 }
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
133
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
134 void CompleteTransit(int state) {
71
1714fd8678ef code cleanup
cin
parents: 66
diff changeset
135 if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, state, TRANSITIONAL_STATE))
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
136 throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state");
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
137 }
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
138
25
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
139 void WaitTransition() {
71
1714fd8678ef code cleanup
cin
parents: 66
diff changeset
140 while (m_state == TRANSITIONAL_STATE) {
25
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
141 /* noop */
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
142 }
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
143 }
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
144
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
145 public bool IsResolved {
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
146 get {
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
147 return m_state > 1;
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
148 }
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
149 }
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
150
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
151 public bool IsCancelled {
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
152 get {
71
1714fd8678ef code cleanup
cin
parents: 66
diff changeset
153 return m_state == CANCELLED_STATE;
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
154 }
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
155 }
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
156
29
768f7deeb55b Added a casting method for promises.
cin
parents: 28
diff changeset
157 public Type PromiseType {
768f7deeb55b Added a casting method for promises.
cin
parents: 28
diff changeset
158 get { return typeof(T); }
768f7deeb55b Added a casting method for promises.
cin
parents: 28
diff changeset
159 }
768f7deeb55b Added a casting method for promises.
cin
parents: 28
diff changeset
160
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
161 /// <summary>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
162 /// Выполняет обещание, сообщая об успешном выполнении.
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
163 /// </summary>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
164 /// <param name="result">Результат выполнения.</param>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
165 /// <exception cref="InvalidOperationException">Данное обещание уже выполнено</exception>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
166 public void Resolve(T result) {
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
167 if (BeginTransit()) {
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
168 m_result = result;
71
1714fd8678ef code cleanup
cin
parents: 66
diff changeset
169 CompleteTransit(SUCCEEDED_STATE);
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
170 OnStateChanged();
25
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
171 } else {
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
172 WaitTransition();
71
1714fd8678ef code cleanup
cin
parents: 66
diff changeset
173 if (m_state != CANCELLED_STATE)
25
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
174 throw new InvalidOperationException("The promise is already resolved");
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
175 }
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
176 }
2
aa367305156b small fixes
cin
parents: 1
diff changeset
177
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
178 /// <summary>
33
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
179 /// Выполняет обещание, сообщая об успешном выполнении. Результатом выполнения будет пустое значения.
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
180 /// </summary>
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
181 /// <remarks>
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
182 /// Данный вариант удобен в случаях, когда интересен факт выполнения операции, нежели полученное значение.
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
183 /// </remarks>
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
184 public void Resolve() {
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
185 Resolve(default(T));
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
186 }
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
187
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
188 /// <summary>
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
189 /// Выполняет обещание, сообщая об ошибке
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
190 /// </summary>
16
cin
parents: 15
diff changeset
191 /// <remarks>
cin
parents: 15
diff changeset
192 /// Поскольку обещание должно работать в многопточной среде, при его выполнении сразу несколько потоков
cin
parents: 15
diff changeset
193 /// могу вернуть ошибку, при этом только первая будет использована в качестве результата, остальные
cin
parents: 15
diff changeset
194 /// будут проигнорированы.
cin
parents: 15
diff changeset
195 /// </remarks>
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
196 /// <param name="error">Исключение возникшее при выполнении операции</param>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
197 /// <exception cref="InvalidOperationException">Данное обещание уже выполнено</exception>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
198 public void Reject(Exception error) {
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
199 if (BeginTransit()) {
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
200 m_error = error;
71
1714fd8678ef code cleanup
cin
parents: 66
diff changeset
201 CompleteTransit(REJECTED_STATE);
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
202 OnStateChanged();
25
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
203 } else {
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
204 WaitTransition();
71
1714fd8678ef code cleanup
cin
parents: 66
diff changeset
205 if (m_state == SUCCEEDED_STATE)
25
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
206 throw new InvalidOperationException("The promise is already resolved");
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
207 }
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
208 }
2
aa367305156b small fixes
cin
parents: 1
diff changeset
209
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
210 /// <summary>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
211 /// Отменяет операцию, если это возможно.
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
212 /// </summary>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
213 /// <returns><c>true</c> Операция была отменена, обработчики не будут вызваны.<c>false</c> отмена не возможна, поскольку обещание уже выполнено и обработчики отработали.</returns>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
214 public bool Cancel() {
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
215 if (m_cancellable && BeginTransit()) {
71
1714fd8678ef code cleanup
cin
parents: 66
diff changeset
216 CompleteTransit(CANCELLED_STATE);
33
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
217 OnStateChanged();
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
218 return true;
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
219 }
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
220 return false;
33
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
221 }
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
222
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
223 // сделано для возвращаемого типа void
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
224 protected void InternalCancel() {
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
225 Cancel();
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
226 }
2
aa367305156b small fixes
cin
parents: 1
diff changeset
227
75
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
228
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
229 public IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error, Action cancel) {
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
230 if (success == null && error == null && cancel == null)
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
231 return this;
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
232
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
233 var medium = new Promise<T>(this, true);
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
234
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
235 AddHandler(success, error, cancel, medium);
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
236
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
237 return medium;
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
238 }
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
239
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
240 /// <summary>
11
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
241 /// Adds new handlers to this promise.
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
242 /// </summary>
11
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
243 /// <param name="success">The handler of the successfully completed operation.
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
244 /// This handler will recieve an operation result as a parameter.</param>
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
245 /// <param name="error">Handles an exception that may occur during the operation and returns the value which will be used as the result of the operation.</param>
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
246 /// <returns>The new promise chained to this one.</returns>
26
f0bf98e4d22c refactoring
cin
parents: 25
diff changeset
247 public IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error) {
11
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
248 if (success == null && error == null)
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
249 return this;
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
250
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
251 var medium = new Promise<T>(this, true);
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
252
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
253 AddHandler(success, error, null, medium);
11
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
254
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
255 return medium;
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
256 }
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
257
75
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
258 public IPromise Then(Action success, ErrorHandler error, Action cancel) {
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
259 return Then(
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
260 x => success(),
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
261 e => {
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
262 error(e);
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
263 return default(T);
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
264 },
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
265 cancel
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
266 );
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
267 }
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
268
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
269 public IPromise Then(Action success, ErrorHandler error) {
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
270 return Then(
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
271 x => success(),
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
272 e => {
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
273 error(e);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
274 return default(T);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
275 }
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
276 );
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
277 }
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
278
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
279 public IPromise Then(Action success) {
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
280 return Then(x => success());
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
281 }
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
282
11
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
283
26
f0bf98e4d22c refactoring
cin
parents: 25
diff changeset
284 public IPromise<T> Then(ResultHandler<T> success) {
11
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
285 if (success == null)
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
286 return this;
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
287
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
288 var medium = new Promise<T>(this, true);
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
289
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
290 AddHandler(success, null, null, medium);
11
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
291
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
292 return medium;
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
293 }
2
aa367305156b small fixes
cin
parents: 1
diff changeset
294
75
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
295 public void Last(ResultHandler<T> success, ErrorHandler error, Action cancel) {
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
296 if (success == null && error == null && cancel == null)
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
297 return;
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
298
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
299 ErrorHandler<T> errorHandler = null;
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
300 if (error != null)
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
301 errorHandler = err => {
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
302 error(err);
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
303 return default(T);
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
304 };
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
305 AddHandler(success, errorHandler, cancel, null);
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
306 }
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
307
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
308 public void Last(ResultHandler<T> success, ErrorHandler error) {
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
309 Last(success, error, null);
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
310 }
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
311
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
312 public void Last(ResultHandler<T> success) {
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
313 Last(success, null, null);
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
314 }
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
315
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
316 public void Last(Action success,ErrorHandler error, Action cancel) {
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
317 Last(x => success(), error, cancel);
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
318 }
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
319
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
320 public void Last(Action success,ErrorHandler error) {
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
321 Last(x => success(), error, null);
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
322 }
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
323
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
324 public void Last(Action success) {
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
325 Last(x => success(), null, null);
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
326 }
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
327
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
328 public IPromise Error(ErrorHandler error) {
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
329 if (error == null)
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
330 return this;
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
331
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
332 var medium = new Promise<T>(this, true);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
333
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
334 AddHandler(
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
335 null,
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
336 e => {
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
337 error(e);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
338 return default(T);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
339 },
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
340 null,
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
341 medium
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
342 );
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
343
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
344 return medium;
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
345 }
2
aa367305156b small fixes
cin
parents: 1
diff changeset
346
11
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
347 /// <summary>
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
348 /// Handles error and allows to keep the promise.
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
349 /// </summary>
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
350 /// <remarks>
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
351 /// If the specified handler throws an exception, this exception will be used to reject the promise.
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
352 /// </remarks>
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
353 /// <param name="handler">The error handler which returns the result of the promise.</param>
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
354 /// <returns>New promise.</returns>
26
f0bf98e4d22c refactoring
cin
parents: 25
diff changeset
355 public IPromise<T> Error(ErrorHandler<T> handler) {
11
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
356 if (handler == null)
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
357 return this;
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
358
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
359 var medium = new Promise<T>(this, true);
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
360
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
361 AddHandler(null, handler, null, medium);
11
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
362
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
363 return medium;
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
364 }
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
365
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
366 /// <summary>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
367 /// Позволяет преобразовать результат выполения операции к новому типу.
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
368 /// </summary>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
369 /// <typeparam name="TNew">Новый тип результата.</typeparam>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
370 /// <param name="mapper">Преобразование результата к новому типу.</param>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
371 /// <param name="error">Обработчик ошибки. Данный обработчик получит
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
372 /// исключение возникшее при выполнении операции.</param>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
373 /// <returns>Новое обещание, которое будет выполнено при выполнении исходного обещания.</returns>
75
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
374 public IPromise<TNew> Then<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler<T> error) {
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
375 if (mapper == null)
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
376 throw new ArgumentNullException("mapper");
2
aa367305156b small fixes
cin
parents: 1
diff changeset
377
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
378 // создаем прицепленное обещание
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
379 var chained = new Promise<TNew>(this, true);
2
aa367305156b small fixes
cin
parents: 1
diff changeset
380
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
381 ResultHandler<T> resultHandler = result => chained.Resolve(mapper(result));
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
382 ErrorHandler<T> errorHandler;
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
383 if (error != null)
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
384 errorHandler = e => {
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
385 try {
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
386 return error(e);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
387 } catch (Exception e2) {
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
388 // в случае ошибки нужно передать исключение дальше по цепочке
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
389 chained.Reject(e2);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
390 }
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
391 return default(T);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
392 };
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
393 else
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
394 errorHandler = e => {
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
395 chained.Reject(e);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
396 return default(T);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
397 };
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
398
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
399
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
400 AddHandler(
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
401 resultHandler,
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
402 errorHandler,
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
403 chained.InternalCancel,
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
404 null
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
405 );
2
aa367305156b small fixes
cin
parents: 1
diff changeset
406
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
407 return chained;
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
408 }
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
409
75
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
410 public IPromise<TNew> Then<TNew>(ResultMapper<T, TNew> mapper) {
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
411 return Then(mapper, null);
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
412 }
2
aa367305156b small fixes
cin
parents: 1
diff changeset
413
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
414 /// <summary>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
415 /// Сцепляет несколько аснхронных операций. Указанная асинхронная операция будет вызвана после
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
416 /// выполнения текущей, а результат текущей операции может быть использован для инициализации
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
417 /// новой операции.
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
418 /// </summary>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
419 /// <typeparam name="TNew">Тип результата указанной асинхронной операции.</typeparam>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
420 /// <param name="chained">Асинхронная операция, которая должна будет начаться после выполнения текущей.</param>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
421 /// <param name="error">Обработчик ошибки. Данный обработчик получит
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
422 /// исключение возникшее при выполнении текуещй операции.</param>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
423 /// <returns>Новое обещание, которое будет выполнено по окончанию указанной аснхронной операции.</returns>
75
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
424 public IPromise<TNew> Then<TNew>(ChainedOperation<T, TNew> chained, ErrorHandler<T> error) {
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
425
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
426 // проблема в том, что на момент связывания еще не начата асинхронная операция, поэтому нужно
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
427 // создать посредника, к которому будут подвызяваться следующие обработчики.
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
428 // когда будет выполнена реальная асинхронная операция, она обратиться к посреднику, чтобы
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
429 // передать через него результаты работы.
10
aa33d0bb8c0c implemeted new cancellable promises concept
cin
parents: 9
diff changeset
430 var medium = new Promise<TNew>(this, true);
2
aa367305156b small fixes
cin
parents: 1
diff changeset
431
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
432 ResultHandler<T> resultHandler = delegate(T result) {
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
433 if (medium.IsCancelled)
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
434 return;
10
aa33d0bb8c0c implemeted new cancellable promises concept
cin
parents: 9
diff changeset
435
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
436 var promise = chained(result);
10
aa33d0bb8c0c implemeted new cancellable promises concept
cin
parents: 9
diff changeset
437
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
438 promise.Then(
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
439 medium.Resolve,
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
440 err => {
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
441 medium.Reject(err);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
442 throw new TransientPromiseException(err);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
443 }
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
444 );
33
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
445
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
446 // notify chained operation that it's not needed anymore
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
447 // порядок вызова Then, Cancelled важен, поскольку от этого
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
448 // зависит IsExclusive
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
449 medium.Cancelled(() => {
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
450 if (promise.IsExclusive)
33
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
451 promise.Cancel();
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
452 });
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
453
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
454 // внешняя отмена связанной операции рассматривается как ошибка
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
455 promise.Cancelled(() => medium.Reject(new OperationCanceledException()));
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
456 };
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
457
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
458 ErrorHandler<T> errorHandler = delegate(Exception e) {
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
459 if (error != null) {
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
460 try {
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
461 return error(e);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
462 } catch (Exception e2) {
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
463 medium.Reject(e2);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
464 return default(T);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
465 }
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
466 }
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
467 // в случае ошибки нужно передать исключение дальше по цепочке
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
468 medium.Reject(e);
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
469 return default(T);
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
470 };
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
471
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
472 AddHandler(
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
473 resultHandler,
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
474 errorHandler,
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
475 medium.InternalCancel,
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
476 null
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
477 );
2
aa367305156b small fixes
cin
parents: 1
diff changeset
478
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
479 return medium;
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
480 }
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
481
75
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
482 public IPromise<TNew> Then<TNew>(ChainedOperation<T, TNew> chained) {
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
483 return Then(chained, null);
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
484 }
2
aa367305156b small fixes
cin
parents: 1
diff changeset
485
26
f0bf98e4d22c refactoring
cin
parents: 25
diff changeset
486 public IPromise<T> Cancelled(Action handler) {
74
c4140283575c minor fixes
cin
parents: 72
diff changeset
487 var medium = new Promise<T>(this, true);
c4140283575c minor fixes
cin
parents: 72
diff changeset
488 AddHandler(null, null, handler, medium);
c4140283575c minor fixes
cin
parents: 72
diff changeset
489 return medium;
10
aa33d0bb8c0c implemeted new cancellable promises concept
cin
parents: 9
diff changeset
490 }
aa33d0bb8c0c implemeted new cancellable promises concept
cin
parents: 9
diff changeset
491
25
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
492 /// <summary>
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
493 /// Adds the specified handler for all cases (success, error, cancel)
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
494 /// </summary>
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
495 /// <param name="handler">The handler that will be called anyway</param>
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
496 /// <returns>self</returns>
26
f0bf98e4d22c refactoring
cin
parents: 25
diff changeset
497 public IPromise<T> Finally(Action handler) {
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
498 if (handler == null)
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
499 throw new ArgumentNullException("handler");
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
500 AddHandler(
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
501 x => handler(),
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
502 e => {
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
503 handler();
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
504 throw new TransientPromiseException(e);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
505 },
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
506 handler,
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
507 null
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
508 );
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
509 return this;
10
aa33d0bb8c0c implemeted new cancellable promises concept
cin
parents: 9
diff changeset
510 }
aa33d0bb8c0c implemeted new cancellable promises concept
cin
parents: 9
diff changeset
511
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
512 /// <summary>
29
768f7deeb55b Added a casting method for promises.
cin
parents: 28
diff changeset
513 /// Преобразует результат обещания к нужному типу
768f7deeb55b Added a casting method for promises.
cin
parents: 28
diff changeset
514 /// </summary>
768f7deeb55b Added a casting method for promises.
cin
parents: 28
diff changeset
515 /// <typeparam name="T2"></typeparam>
768f7deeb55b Added a casting method for promises.
cin
parents: 28
diff changeset
516 /// <returns></returns>
768f7deeb55b Added a casting method for promises.
cin
parents: 28
diff changeset
517 public IPromise<T2> Cast<T2>() {
75
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
518 return Then(x => (T2)(object)x, null);
29
768f7deeb55b Added a casting method for promises.
cin
parents: 28
diff changeset
519 }
768f7deeb55b Added a casting method for promises.
cin
parents: 28
diff changeset
520
768f7deeb55b Added a casting method for promises.
cin
parents: 28
diff changeset
521 /// <summary>
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
522 /// Дожидается отложенного обещания и в случае успеха, возвращает
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
523 /// его, результат, в противном случае бросает исключение.
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
524 /// </summary>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
525 /// <remarks>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
526 /// <para>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
527 /// Если ожидание обещания было прервано по таймауту, это не значит,
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
528 /// что обещание было отменено или что-то в этом роде, это только
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
529 /// означает, что мы его не дождались, однако все зарегистрированные
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
530 /// обработчики, как были так остались и они будут вызваны, когда
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
531 /// обещание будет выполнено.
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
532 /// </para>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
533 /// <para>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
534 /// Такое поведение вполне оправдано поскольку таймаут может истечь
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
535 /// в тот момент, когда началась обработка цепочки обработчиков, и
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
536 /// к тому же текущее обещание может стоять в цепочке обещаний и его
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
537 /// отклонение может привести к непрогнозируемому результату.
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
538 /// </para>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
539 /// </remarks>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
540 /// <param name="timeout">Время ожидания</param>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
541 /// <returns>Результат выполнения обещания</returns>
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
542 public T Join(int timeout) {
10
aa33d0bb8c0c implemeted new cancellable promises concept
cin
parents: 9
diff changeset
543 var evt = new ManualResetEvent(false);
75
4439140706d0 major refactoring, added tasks support
cin
parents: 74
diff changeset
544 Finally(() => evt.Set());
2
aa367305156b small fixes
cin
parents: 1
diff changeset
545
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
546 if (!evt.WaitOne(timeout, true))
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
547 throw new TimeoutException();
2
aa367305156b small fixes
cin
parents: 1
diff changeset
548
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
549 switch (m_state) {
71
1714fd8678ef code cleanup
cin
parents: 66
diff changeset
550 case SUCCEEDED_STATE:
10
aa33d0bb8c0c implemeted new cancellable promises concept
cin
parents: 9
diff changeset
551 return m_result;
71
1714fd8678ef code cleanup
cin
parents: 66
diff changeset
552 case CANCELLED_STATE:
10
aa33d0bb8c0c implemeted new cancellable promises concept
cin
parents: 9
diff changeset
553 throw new OperationCanceledException();
71
1714fd8678ef code cleanup
cin
parents: 66
diff changeset
554 case REJECTED_STATE:
10
aa33d0bb8c0c implemeted new cancellable promises concept
cin
parents: 9
diff changeset
555 throw new TargetInvocationException(m_error);
aa33d0bb8c0c implemeted new cancellable promises concept
cin
parents: 9
diff changeset
556 default:
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
557 throw new ApplicationException(String.Format("Invalid promise state {0}", m_state));
10
aa33d0bb8c0c implemeted new cancellable promises concept
cin
parents: 9
diff changeset
558 }
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
559 }
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
560
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
561 public T Join() {
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
562 return Join(Timeout.Infinite);
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
563 }
2
aa367305156b small fixes
cin
parents: 1
diff changeset
564
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
565 void AddHandler(ResultHandler<T> success, ErrorHandler<T> error, Action cancel, Promise<T> medium) {
33
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
566 if (success != null || error != null)
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
567 Interlocked.Increment(ref m_childrenCount);
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
568
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
569 var handler = new HandlerDescriptor {
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
570 resultHandler = success,
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
571 errorHandler = error,
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
572 cancellHandler = cancel,
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
573 medium = medium
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
574 };
2
aa367305156b small fixes
cin
parents: 1
diff changeset
575
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
576 bool queued;
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
577
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
578 if (!IsResolved) {
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
579 m_handlers.Enqueue(handler);
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
580 queued = true;
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
581 } else {
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
582 // the promise is in resolved state, just invoke the handled with minimum overhead
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
583 queued = false;
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
584 InvokeHandler(handler);
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
585 }
2
aa367305156b small fixes
cin
parents: 1
diff changeset
586
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
587 if (queued && IsResolved && m_handlers.TryDequeue(out handler))
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
588 // if the promise have been resolved while we was adding handler to the queue
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
589 // we can't guarantee that someone is still processing it
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
590 // therefore we will fetch a handler from the queue and execute it
27
cin
parents: 26
diff changeset
591 // note that fetched handler may be not the one that we have added
cin
parents: 26
diff changeset
592 // even we can fetch no handlers at all :)
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
593 InvokeHandler(handler);
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
594 }
2
aa367305156b small fixes
cin
parents: 1
diff changeset
595
27
cin
parents: 26
diff changeset
596 protected virtual void InvokeHandler(HandlerDescriptor handler) {
10
aa33d0bb8c0c implemeted new cancellable promises concept
cin
parents: 9
diff changeset
597 switch (m_state) {
71
1714fd8678ef code cleanup
cin
parents: 66
diff changeset
598 case SUCCEEDED_STATE:
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
599 handler.Resolve(m_result);
10
aa33d0bb8c0c implemeted new cancellable promises concept
cin
parents: 9
diff changeset
600 break;
71
1714fd8678ef code cleanup
cin
parents: 66
diff changeset
601 case REJECTED_STATE:
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
602 handler.Reject(m_error);
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
603 break;
71
1714fd8678ef code cleanup
cin
parents: 66
diff changeset
604 case CANCELLED_STATE:
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
605 handler.Cancel();
10
aa33d0bb8c0c implemeted new cancellable promises concept
cin
parents: 9
diff changeset
606 break;
aa33d0bb8c0c implemeted new cancellable promises concept
cin
parents: 9
diff changeset
607 default:
aa33d0bb8c0c implemeted new cancellable promises concept
cin
parents: 9
diff changeset
608 // do nothing
aa33d0bb8c0c implemeted new cancellable promises concept
cin
parents: 9
diff changeset
609 return;
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
610 }
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
611 }
2
aa367305156b small fixes
cin
parents: 1
diff changeset
612
65
653c4e04968b minor changes
cin
parents: 33
diff changeset
613 void OnStateChanged() {
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
614 HandlerDescriptor handler;
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
615 while (m_handlers.TryDequeue(out handler))
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
616 InvokeHandler(handler);
11
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
617 }
6ec82bf68c8e refactoring
cin
parents: 10
diff changeset
618
9
cin
parents: 7
diff changeset
619 public bool IsExclusive {
cin
parents: 7
diff changeset
620 get {
19
e3935fdf59a2 Promise is rewritten to use interlocked operations instead of locks
cin
parents: 16
diff changeset
621 return m_childrenCount <= 1;
9
cin
parents: 7
diff changeset
622 }
cin
parents: 7
diff changeset
623 }
cin
parents: 7
diff changeset
624
25
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
625 /// <summary>
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
626 /// Объединяет несколько обещаний в одно, результатом которого является массив результатов других обещаний.
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
627 /// Если хотябы одно из переданных обещаний не будет выполнено, то новое обещение тоже не будет выполнено.
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
628 /// При отмене нового обещания, переданные обещания также будут отменены, если никто больше на них не подписан.
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
629 /// </summary>
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
630 /// <param name="promises">Список обещаний. Если список пустой, то результирующее обещание возвращается уже выполненным.</param>
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
631 /// <returns>Обещание объединяющее в себе результат переданных обещаний.</returns>
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
632 /// <exception cref="ArgumentNullException"><paramref name="promises"/> не может быть null</exception>
30
2fad2d1f4b03 small refactoring, cleanup.
cin
parents: 29
diff changeset
633 public static IPromise<T[]> CreateComposite(IList<IPromise<T>> promises) {
25
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
634 if (promises == null)
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
635 throw new ArgumentNullException();
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
636
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
637 // создаем аккумулятор для результатов и результирующее обещание
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
638 var result = new T[promises.Count];
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
639 var promise = new Promise<T[]>();
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
640
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
641 // special case
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
642 if (promises.Count == 0) {
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
643 promise.Resolve(result);
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
644 return promise;
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
645 }
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
646
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
647 int pending = promises.Count;
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
648
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
649 for (int i = 0; i < promises.Count; i++) {
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
650 var dest = i;
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
651
33
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
652 if (promises[i] != null) {
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
653 promises[i].Then(
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
654 x => {
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
655 result[dest] = x;
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
656 if (Interlocked.Decrement(ref pending) == 0)
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
657 promise.Resolve(result);
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
658 },
72
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
659 e => {
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
660 promise.Reject(e);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
661 return default(T);
d67b95eddaf4 promises refactoring
cin
parents: 71
diff changeset
662 }
33
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
663 );
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
664 } else {
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
665 if (Interlocked.Decrement(ref pending) == 0)
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
666 promise.Resolve(result);
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
667 }
25
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
668 }
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
669
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
670 promise.Cancelled(
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
671 () => {
33
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
672 foreach (var d in promises)
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
673 if (d != null && d.IsExclusive)
25
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
674 d.Cancel();
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
675 }
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
676 );
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
677
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
678 return promise;
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
679 }
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
680
33
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
681 /// <summary>
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
682 /// Объединяет несколько обещаний в одно. Результирующее обещание будет выполнено при
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
683 /// выполнении всех указанных обещаний. При этом возвращаемые значения первичных обещаний
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
684 /// игнорируются.
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
685 /// </summary>
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
686 /// <param name="promises">Коллекция первичных обещаний, которые будут объеденены в одно.</param>
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
687 /// <returns>Новое обещание, объединяющее в себе переданные.</returns>
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
688 /// <remarks>
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
689 /// Если в коллекции встречаюься <c>null</c>, то они воспринимаются как выполненные обещания.
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
690 /// </remarks>
66
790e8a997d30 Refactoring
cin
parents: 65
diff changeset
691 public static IPromise CreateComposite(ICollection<IPromise> promises) {
33
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
692 if (promises == null)
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
693 throw new ArgumentNullException();
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
694 if (promises.Count == 0)
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
695 return Promise<object>.ResultToPromise(null);
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
696
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
697 int countdown = promises.Count;
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
698
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
699 var result = new Promise<object>();
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
700
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
701 foreach (var d in promises) {
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
702 if (d == null) {
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
703 if (Interlocked.Decrement(ref countdown) == 0)
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
704 result.Resolve(null);
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
705 } else {
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
706 d.Then(() => {
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
707 if (Interlocked.Decrement(ref countdown) == 0)
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
708 result.Resolve(null);
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
709 });
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
710 }
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
711 }
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
712
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
713 result.Cancelled(() => {
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
714 foreach (var d in promises)
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
715 if (d != null && d.IsExclusive)
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
716 d.Cancel();
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
717 });
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
718
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
719 return result;
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
720 }
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
721
25
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
722 public static Promise<T> ResultToPromise(T result) {
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
723 var p = new Promise<T>();
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
724 p.Resolve(result);
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
725 return p;
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
726 }
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
727
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
728 public static Promise<T> ExceptionToPromise(Exception error) {
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
729 if (error == null)
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
730 throw new ArgumentNullException();
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
731
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
732 var p = new Promise<T>();
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
733 p.Reject(error);
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
734 return p;
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
735 }
9bf5b23650c9 refactoring
cin
parents: 19
diff changeset
736
33
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
737 #region IPromiseBase explicit implementation
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
738
66
790e8a997d30 Refactoring
cin
parents: 65
diff changeset
739 IPromise IPromise.Error(ErrorHandler error) {
33
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
740 return Error(error);
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
741 }
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
742
66
790e8a997d30 Refactoring
cin
parents: 65
diff changeset
743 IPromise IPromise.Finally(Action handler) {
33
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
744 return Finally(handler);
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
745 }
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
746
66
790e8a997d30 Refactoring
cin
parents: 65
diff changeset
747 IPromise IPromise.Cancelled(Action handler) {
33
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
748 return Cancelled(handler);
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
749 }
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
750
66
790e8a997d30 Refactoring
cin
parents: 65
diff changeset
751 void IPromise.Join() {
33
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
752 Join();
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
753 }
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
754
66
790e8a997d30 Refactoring
cin
parents: 65
diff changeset
755 void IPromise.Join(int timeout) {
33
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
756 Join(timeout);
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
757 }
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
758
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
759 #endregion
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
760
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
761
b255e4aeef17 removed the reference to the parent from the promise object this allows
cin
parents: 32
diff changeset
762
6
dfa21d507bc5 *refactoring: Promise.Then now returns a new chained promise
cin
parents: 2
diff changeset
763 }
2
aa367305156b small fixes
cin
parents: 1
diff changeset
764 }