annotate Implab/Promise.cs @ 33:b255e4aeef17

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