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