| @@ -0,0 +1,19 | |||||
|
|
1 | using System; | |||
|
|
2 | using System.Collections.Generic; | |||
|
|
3 | using System.Linq; | |||
|
|
4 | using System.Text; | |||
|
|
5 | ||||
|
|
6 | namespace Implab { | |||
|
|
7 | public interface IPromiseBase: ICancellable { | |||
|
|
8 | /// <summary> | |||
|
|
9 | /// Check whereather the promise has no more than one dependent promise. | |||
|
|
10 | /// </summary> | |||
|
|
11 | bool IsExclusive { | |||
|
|
12 | get; | |||
|
|
13 | } | |||
|
|
14 | ||||
|
|
15 | bool IsResolved { get; } | |||
|
|
16 | ||||
|
|
17 | bool IsCancelled { get; } | |||
|
|
18 | } | |||
|
|
19 | } | |||
| @@ -5,15 +5,11 using System.Text; | |||||
| 5 |
|
5 | |||
| 6 | namespace Implab |
|
6 | namespace Implab | |
| 7 | { |
|
7 | { | |
| 8 |
public interface IPromise: I |
|
8 | public interface IPromise<T>: IPromiseBase | |
| 9 | { |
|
9 | { | |
| 10 | /// <summary> |
|
10 | ||
| 11 | /// Check whereather the promise has no more than one dependent promise. |
|
11 | ||
| 12 | /// </summary> |
|
12 | ||
| 13 | bool IsExclusive |
|
|||
| 14 | { |
|
|||
| 15 | get; |
|
|||
| 16 | } |
|
|||
| 17 |
|
13 | |||
| 18 |
|
14 | |||
| 19 | } |
|
15 | } | |
| @@ -4,9 +4,11 using System.Linq; | |||||
| 4 | using System.Text; |
|
4 | using System.Text; | |
| 5 |
|
5 | |||
| 6 | namespace Implab { |
|
6 | namespace Implab { | |
| 7 | public interface ITaskController: IProgressHandler { |
|
7 | public interface ITaskController: IProgressHandler, ICancellable { | |
| 8 | bool Cancelled { |
|
8 | bool IsCancelled { | |
| 9 | get; |
|
9 | get; | |
| 10 | } |
|
10 | } | |
|
|
11 | ||||
|
|
12 | event EventHandler Cancelled; | |||
| 11 | } |
|
13 | } | |
| 12 | } |
|
14 | } | |
| @@ -36,6 +36,7 | |||||
| 36 | <Compile Include="IProgressHandler.cs" /> |
|
36 | <Compile Include="IProgressHandler.cs" /> | |
| 37 | <Compile Include="IProgressNotifier.cs" /> |
|
37 | <Compile Include="IProgressNotifier.cs" /> | |
| 38 | <Compile Include="IPromise.cs" /> |
|
38 | <Compile Include="IPromise.cs" /> | |
|
|
39 | <Compile Include="IPromiseBase.cs" /> | |||
| 39 | <Compile Include="ITaskController.cs" /> |
|
40 | <Compile Include="ITaskController.cs" /> | |
| 40 | <Compile Include="ManagedPromise.cs" /> |
|
41 | <Compile Include="ManagedPromise.cs" /> | |
| 41 | <Compile Include="Parallels\DispatchPool.cs" /> |
|
42 | <Compile Include="Parallels\DispatchPool.cs" /> | |
| @@ -168,45 +168,5 namespace Implab.Parallels { | |||||
| 168 | return promise.Anyway(() => semaphore.Dispose()); |
|
168 | return promise.Anyway(() => semaphore.Dispose()); | |
| 169 | } |
|
169 | } | |
| 170 |
|
170 | |||
| 171 | /* |
|
|||
| 172 | this method is pretty fast, but it may cause a stack overflow if an element transformation is made faster then the next operation is |
|
|||
| 173 | be chained, in this case the syncronous callback invocation will occur |
|
|||
| 174 |
|
||||
| 175 | public static Promise<TDst[]> ChainedMap2<TSrc, TDst>(this TSrc[] source, ChainedOperation<TSrc, TDst> transform, int threads) { |
|
|||
| 176 | if (source == null) |
|
|||
| 177 | throw new ArgumentNullException("source"); |
|
|||
| 178 | if (transform == null) |
|
|||
| 179 | throw new ArgumentNullException("transform"); |
|
|||
| 180 | if (threads <= 0) |
|
|||
| 181 | throw new ArgumentOutOfRangeException("Threads number must be greater then zero"); |
|
|||
| 182 |
|
||||
| 183 | var promise = new Promise<TDst[]>(); |
|
|||
| 184 | var res = new TDst[source.Length]; |
|
|||
| 185 | var index = -1; // we will start with increment |
|
|||
| 186 | var len = source.Length; |
|
|||
| 187 | var pending = len; |
|
|||
| 188 |
|
||||
| 189 | Action<int> callback = null; |
|
|||
| 190 | callback = (current) => { |
|
|||
| 191 | if (current < len) { |
|
|||
| 192 | transform(source[current]) |
|
|||
| 193 | .Then( |
|
|||
| 194 | x => { |
|
|||
| 195 | res[current] = x; |
|
|||
| 196 | if (Interlocked.Decrement(ref pending) == 0) |
|
|||
| 197 | promise.Resolve(res); |
|
|||
| 198 | else |
|
|||
| 199 | callback(Interlocked.Increment(ref index)); |
|
|||
| 200 | }, |
|
|||
| 201 | e => promise.Reject(e) |
|
|||
| 202 | ); |
|
|||
| 203 | } |
|
|||
| 204 | }; |
|
|||
| 205 |
|
||||
| 206 | for (int i = 0; i < threads; i++) |
|
|||
| 207 | callback(Interlocked.Increment(ref index)); |
|
|||
| 208 | return promise; |
|
|||
| 209 | } |
|
|||
| 210 | */ |
|
|||
| 211 | } |
|
171 | } | |
| 212 | } |
|
172 | } | |
| @@ -1,28 +1,28 | |||||
| 1 | using System; |
|
1 | using System; | |
| 2 | using System.Threading; |
|
2 | using System.Threading; | |
| 3 |
|
3 | |||
| 4 | namespace Implab.Parallels { |
|
4 | namespace Implab.Parallels { | |
| 5 | /// <summary> |
|
5 | /// <summary> | |
| 6 | /// ΠΠ»Π°ΡΡ Π΄Π»Ρ ΡΠ°ΡΠΏΠ°ΡΠ°Π»Π΅Π»ΠΈΠ²Π°Π½ΠΈΡ Π·Π°Π΄Π°Ρ. |
|
6 | /// ΠΠ»Π°ΡΡ Π΄Π»Ρ ΡΠ°ΡΠΏΠ°ΡΠ°Π»Π΅Π»ΠΈΠ²Π°Π½ΠΈΡ Π·Π°Π΄Π°Ρ. | |
| 7 | /// </summary> |
|
7 | /// </summary> | |
| 8 | /// <remarks> |
|
8 | /// <remarks> | |
| 9 | /// ΠΡΠΏΠΎΠ»ΡΠ·ΡΡ Π΄Π°Π½Π½ΡΠΉ ΠΊΠ»Π°ΡΡ ΠΈ Π»ΡΠΌΠ΄Π° Π²ΡΡΠ°ΠΆΠ΅Π½ΠΈΡ ΠΌΠΎΠΆΠ½ΠΎ ΡΠ°ΡΠΏΠ°ΡΠ°Π»Π»Π΅Π»ΠΈΡΡ |
|
9 | /// ΠΡΠΏΠΎΠ»ΡΠ·ΡΡ Π΄Π°Π½Π½ΡΠΉ ΠΊΠ»Π°ΡΡ ΠΈ Π»ΡΠΌΠ΄Π° Π²ΡΡΠ°ΠΆΠ΅Π½ΠΈΡ ΠΌΠΎΠΆΠ½ΠΎ ΡΠ°ΡΠΏΠ°ΡΠ°Π»Π»Π΅Π»ΠΈΡΡ | |
| 10 | /// Π²ΡΡΠΈΡΠ»Π΅Π½ΠΈΡ, Π΄Π»Ρ ΡΡΠΎΠ³ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ ΠΊΠΎΠ½ΡΠ΅ΠΏΡΠΈΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΉ. |
|
10 | /// Π²ΡΡΠΈΡΠ»Π΅Π½ΠΈΡ, Π΄Π»Ρ ΡΡΠΎΠ³ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ ΠΊΠΎΠ½ΡΠ΅ΠΏΡΠΈΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΉ. | |
| 11 | /// </remarks> |
|
11 | /// </remarks> | |
| 12 | public static class AsyncPool { |
|
12 | public static class AsyncPool { | |
| 13 |
|
13 | |||
| 14 | public static Promise<T> Invoke<T>(Func<T> func) { |
|
14 | public static Promise<T> Invoke<T>(Func<T> func) { | |
| 15 | var p = new Promise<T>(); |
|
15 | var p = new Promise<T>(); | |
| 16 |
|
16 | |||
| 17 | ThreadPool.QueueUserWorkItem(param => { |
|
17 | ThreadPool.QueueUserWorkItem(param => { | |
| 18 | try { |
|
18 | try { | |
| 19 | p.Resolve(func()); |
|
19 | p.Resolve(func()); | |
| 20 | } catch(Exception e) { |
|
20 | } catch(Exception e) { | |
| 21 | p.Reject(e); |
|
21 | p.Reject(e); | |
| 22 | } |
|
22 | } | |
| 23 | }); |
|
23 | }); | |
| 24 |
|
24 | |||
| 25 | return p; |
|
25 | return p; | |
| 26 | } |
|
26 | } | |
| 27 |
|
27 | |||
| 28 | public static Promise<T> InvokeNewThread<T>(Func<T> func) { |
|
28 | public static Promise<T> InvokeNewThread<T>(Func<T> func) { | |
| @@ -39,6 +39,6 namespace Implab.Parallels { | |||||
| 39 | worker.Start(); |
|
39 | worker.Start(); | |
| 40 |
|
40 | |||
| 41 | return p; |
|
41 | return p; | |
| 42 | } |
|
42 | } | |
| 43 | } |
|
43 | } | |
| 44 | } |
|
44 | } | |
| @@ -47,7 +47,7 namespace Implab { | |||||
| 47 | /// ΡΠΎΠ»ΡΠΊΠΎ ΠΈΠ½ΠΈΡΠΈΠ°ΡΠΎΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΡ ΠΈΠ½Π°ΡΠ΅ ΠΌΠΎΠ³ΡΡ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡΡΡ ΠΏΡΠΎΡΠΈΠ²ΠΎΡΠ΅ΡΠΈΡ. |
|
47 | /// ΡΠΎΠ»ΡΠΊΠΎ ΠΈΠ½ΠΈΡΠΈΠ°ΡΠΎΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΡ ΠΈΠ½Π°ΡΠ΅ ΠΌΠΎΠ³ΡΡ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡΡΡ ΠΏΡΠΎΡΠΈΠ²ΠΎΡΠ΅ΡΠΈΡ. | |
| 48 | /// </para> |
|
48 | /// </para> | |
| 49 | /// </remarks> |
|
49 | /// </remarks> | |
| 50 | public class Promise<T> : IPromise { |
|
50 | public class Promise<T> : IPromise<T> { | |
| 51 |
|
51 | |||
| 52 | struct HandlerDescriptor { |
|
52 | struct HandlerDescriptor { | |
| 53 | public ResultHandler<T> resultHandler; |
|
53 | public ResultHandler<T> resultHandler; | |
| @@ -82,11 +82,11 namespace Implab { | |||||
| 82 |
|
82 | |||
| 83 | const int UnresolvedSate = 0; |
|
83 | const int UnresolvedSate = 0; | |
| 84 | const int TransitionalState = 1; |
|
84 | const int TransitionalState = 1; | |
| 85 |
const int |
|
85 | const int SucceededState = 2; | |
| 86 | const int RejectedState = 3; |
|
86 | const int RejectedState = 3; | |
| 87 | const int CancelledState = 4; |
|
87 | const int CancelledState = 4; | |
| 88 |
|
88 | |||
| 89 | readonly IPromise m_parent; |
|
89 | readonly IPromiseBase m_parent; | |
| 90 | readonly bool m_cancellable; |
|
90 | readonly bool m_cancellable; | |
| 91 |
|
91 | |||
| 92 | int m_childrenCount = 0; |
|
92 | int m_childrenCount = 0; | |
| @@ -100,7 +100,7 namespace Implab { | |||||
| 100 | m_cancellable = true; |
|
100 | m_cancellable = true; | |
| 101 | } |
|
101 | } | |
| 102 |
|
102 | |||
| 103 | public Promise(IPromise parent, bool cancellable) { |
|
103 | public Promise(IPromiseBase parent, bool cancellable) { | |
| 104 | m_cancellable = cancellable; |
|
104 | m_cancellable = cancellable; | |
| 105 | m_parent = parent; |
|
105 | m_parent = parent; | |
| 106 | } |
|
106 | } | |
| @@ -119,6 +119,12 namespace Implab { | |||||
| 119 | throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state"); |
|
119 | throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state"); | |
| 120 | } |
|
120 | } | |
| 121 |
|
121 | |||
|
|
122 | void WaitTransition() { | |||
|
|
123 | while (m_state == TransitionalState) { | |||
|
|
124 | /* noop */ | |||
|
|
125 | } | |||
|
|
126 | } | |||
|
|
127 | ||||
| 122 | public bool IsResolved { |
|
128 | public bool IsResolved { | |
| 123 | get { |
|
129 | get { | |
| 124 | return m_state > 1; |
|
130 | return m_state > 1; | |
| @@ -139,10 +145,13 namespace Implab { | |||||
| 139 | public void Resolve(T result) { |
|
145 | public void Resolve(T result) { | |
| 140 | if (BeginTransit()) { |
|
146 | if (BeginTransit()) { | |
| 141 | m_result = result; |
|
147 | m_result = result; | |
| 142 |
CompleteTransit( |
|
148 | CompleteTransit(SucceededState); | |
| 143 | OnStateChanged(); |
|
149 | OnStateChanged(); | |
| 144 | } else if (m_state != CancelledState) |
|
150 | } else { | |
| 145 | throw new InvalidOperationException("The promise is already resolved"); |
|
151 | WaitTransition(); | |
|
|
152 | if (m_state != CancelledState) | |||
|
|
153 | throw new InvalidOperationException("The promise is already resolved"); | |||
|
|
154 | } | |||
| 146 | } |
|
155 | } | |
| 147 |
|
156 | |||
| 148 | /// <summary> |
|
157 | /// <summary> | |
| @@ -160,8 +169,11 namespace Implab { | |||||
| 160 | m_error = error; |
|
169 | m_error = error; | |
| 161 | CompleteTransit(RejectedState); |
|
170 | CompleteTransit(RejectedState); | |
| 162 | OnStateChanged(); |
|
171 | OnStateChanged(); | |
| 163 | } else if (m_state == ResolvedState) |
|
172 | } else { | |
| 164 | throw new InvalidOperationException("The promise is already resolved"); |
|
173 | WaitTransition(); | |
|
|
174 | if (m_state == SucceededState) | |||
|
|
175 | throw new InvalidOperationException("The promise is already resolved"); | |||
|
|
176 | } | |||
| 165 | } |
|
177 | } | |
| 166 |
|
178 | |||
| 167 | /// <summary> |
|
179 | /// <summary> | |
| @@ -197,6 +209,9 namespace Implab { | |||||
| 197 | ErrorHandler errorHandler; |
|
209 | ErrorHandler errorHandler; | |
| 198 | if (error != null) |
|
210 | if (error != null) | |
| 199 | errorHandler = x => { |
|
211 | errorHandler = x => { | |
|
|
212 | // Π½Π΅ΡΠΌΠΎΡΡΡ Π½Π° ΡΠΎ, ΡΡΠΎ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΠΎΡΠΈΠ±ΠΊΠΈ Π²ΡΠ·ΡΠ²Π°Π΅ΡΡΡ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎ, | |||
|
|
213 | // Ρ.Π΅. Π²ΠΎΠ·Π½ΠΈΠΊΡΠΈΠ΅ Π² Π½Π΅ΠΌ ΠΎΡΠΈΠ±ΠΊΠΈ Π±ΡΠ΄ΡΡ ΠΏΠΎΠ΄Π°Π²Π»Π΅Π½Ρ, Π½Π°ΠΌ Π½ΡΠΆΠ½ΠΎ | |||
|
|
214 | // Π³Π°ΡΠ°Π½ΡΠΈΡΠΎΠ²Π°ΡΡ, ΡΡΠΎ ΠΎΡΠΈΠ±ΠΊΠ° Π±ΡΠ΄Π΅Ρ ΠΏΠ΅ΡΠ΅Π΄Π°Π½Π° Π΄Π°Π»ΡΡΠ΅ ΠΏΠΎ ΡΠ΅ΠΏΠΎΡΠΊΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΉ | |||
| 200 | try { |
|
215 | try { | |
| 201 | error(x); |
|
216 | error(x); | |
| 202 | } catch { } |
|
217 | } catch { } | |
| @@ -238,8 +253,9 namespace Implab { | |||||
| 238 | errorHandler = x => { |
|
253 | errorHandler = x => { | |
| 239 | try { |
|
254 | try { | |
| 240 | medium.Resolve(error(x)); |
|
255 | medium.Resolve(error(x)); | |
| 241 |
} catch { |
|
256 | } catch(Exception e) { | |
| 242 |
medium.Reject( |
|
257 | medium.Reject(e); | |
|
|
258 | } | |||
| 243 | }; |
|
259 | }; | |
| 244 | else |
|
260 | else | |
| 245 | errorHandler = medium.Reject; |
|
261 | errorHandler = medium.Reject; | |
| @@ -257,7 +273,7 namespace Implab { | |||||
| 257 | var medium = new Promise<T>(this, true); |
|
273 | var medium = new Promise<T>(this, true); | |
| 258 |
|
274 | |||
| 259 | ResultHandler<T> resultHandler; |
|
275 | ResultHandler<T> resultHandler; | |
| 260 |
|
276 | |||
| 261 | if (success != null) |
|
277 | if (success != null) | |
| 262 | resultHandler = x => { |
|
278 | resultHandler = x => { | |
| 263 | success(x); |
|
279 | success(x); | |
| @@ -430,6 +446,11 namespace Implab { | |||||
| 430 | return this; |
|
446 | return this; | |
| 431 | } |
|
447 | } | |
| 432 |
|
448 | |||
|
|
449 | /// <summary> | |||
|
|
450 | /// Adds the specified handler for all cases (success, error, cancel) | |||
|
|
451 | /// </summary> | |||
|
|
452 | /// <param name="handler">The handler that will be called anyway</param> | |||
|
|
453 | /// <returns>self</returns> | |||
| 433 | public Promise<T> Finally(Action handler) { |
|
454 | public Promise<T> Finally(Action handler) { | |
| 434 | if (handler == null) |
|
455 | if (handler == null) | |
| 435 | throw new ArgumentNullException("handler"); |
|
456 | throw new ArgumentNullException("handler"); | |
| @@ -471,7 +492,7 namespace Implab { | |||||
| 471 | throw new TimeoutException(); |
|
492 | throw new TimeoutException(); | |
| 472 |
|
493 | |||
| 473 | switch (m_state) { |
|
494 | switch (m_state) { | |
| 474 |
case |
|
495 | case SucceededState: | |
| 475 | return m_result; |
|
496 | return m_result; | |
| 476 | case CancelledState: |
|
497 | case CancelledState: | |
| 477 | throw new OperationCanceledException(); |
|
498 | throw new OperationCanceledException(); | |
| @@ -517,7 +538,7 namespace Implab { | |||||
| 517 |
|
538 | |||
| 518 | void InvokeHandler(HandlerDescriptor handler) { |
|
539 | void InvokeHandler(HandlerDescriptor handler) { | |
| 519 | switch (m_state) { |
|
540 | switch (m_state) { | |
| 520 |
case |
|
541 | case SucceededState: | |
| 521 | handler.Resolve(m_result); |
|
542 | handler.Resolve(m_result); | |
| 522 | break; |
|
543 | break; | |
| 523 | case RejectedState: |
|
544 | case RejectedState: | |
| @@ -538,8 +559,6 namespace Implab { | |||||
| 538 | InvokeHandler(handler); |
|
559 | InvokeHandler(handler); | |
| 539 | } |
|
560 | } | |
| 540 |
|
561 | |||
| 541 |
|
||||
| 542 |
|
||||
| 543 | public bool IsExclusive { |
|
562 | public bool IsExclusive { | |
| 544 | get { |
|
563 | get { | |
| 545 | return m_childrenCount <= 1; |
|
564 | return m_childrenCount <= 1; | |
| @@ -560,5 +579,68 namespace Implab { | |||||
| 560 | } |
|
579 | } | |
| 561 | } |
|
580 | } | |
| 562 |
|
581 | |||
|
|
582 | /// <summary> | |||
|
|
583 | /// ΠΠ±ΡΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ, ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠΎΠΌ ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ ΡΠ²Π»ΡΠ΅ΡΡΡ ΠΌΠ°ΡΡΠΈΠ² ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠΎΠ² Π΄ΡΡΠ³ΠΈΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΉ. | |||
|
|
584 | /// ΠΡΠ»ΠΈ Ρ ΠΎΡΡΠ±Ρ ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΠΏΠ΅ΡΠ΅Π΄Π°Π½Π½ΡΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΉ Π½Π΅ Π±ΡΠ΄Π΅Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΎ, ΡΠΎ Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅ΡΠ΅Π½ΠΈΠ΅ ΡΠΎΠΆΠ΅ Π½Π΅ Π±ΡΠ΄Π΅Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΎ. | |||
|
|
585 | /// ΠΡΠΈ ΠΎΡΠΌΠ΅Π½Π΅ Π½ΠΎΠ²ΠΎΠ³ΠΎ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΡ, ΠΏΠ΅ΡΠ΅Π΄Π°Π½Π½ΡΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΡ ΡΠ°ΠΊΠΆΠ΅ Π±ΡΠ΄ΡΡ ΠΎΡΠΌΠ΅Π½Π΅Π½Ρ, Π΅ΡΠ»ΠΈ Π½ΠΈΠΊΡΠΎ Π±ΠΎΠ»ΡΡΠ΅ Π½Π° Π½ΠΈΡ Π½Π΅ ΠΏΠΎΠ΄ΠΏΠΈΡΠ°Π½. | |||
|
|
586 | /// </summary> | |||
|
|
587 | /// <param name="promises">Π‘ΠΏΠΈΡΠΎΠΊ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΉ. ΠΡΠ»ΠΈ ΡΠΏΠΈΡΠΎΠΊ ΠΏΡΡΡΠΎΠΉ, ΡΠΎ ΡΠ΅Π·ΡΠ»ΡΡΠΈΡΡΡΡΠ΅Π΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΡΡΡ ΡΠΆΠ΅ Π²ΡΠΏΠΎΠ»Π½Π΅Π½Π½ΡΠΌ.</param> | |||
|
|
588 | /// <returns>ΠΠ±Π΅ΡΠ°Π½ΠΈΠ΅ ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½ΡΡΡΠ΅Π΅ Π² ΡΠ΅Π±Π΅ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ ΠΏΠ΅ΡΠ΅Π΄Π°Π½Π½ΡΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΉ.</returns> | |||
|
|
589 | /// <exception cref="ArgumentNullException"><paramref name="promises"/> Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ null</exception> | |||
|
|
590 | public static Promise<T[]> CreateComposite(IList<Promise<T>> promises) { | |||
|
|
591 | if (promises == null) | |||
|
|
592 | throw new ArgumentNullException(); | |||
|
|
593 | ||||
|
|
594 | // ΡΠΎΠ·Π΄Π°Π΅ΠΌ Π°ΠΊΠΊΡΠΌΡΠ»ΡΡΠΎΡ Π΄Π»Ρ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠΎΠ² ΠΈ ΡΠ΅Π·ΡΠ»ΡΡΠΈΡΡΡΡΠ΅Π΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ | |||
|
|
595 | var result = new T[promises.Count]; | |||
|
|
596 | var promise = new Promise<T[]>(); | |||
|
|
597 | ||||
|
|
598 | // special case | |||
|
|
599 | if (promises.Count == 0) { | |||
|
|
600 | promise.Resolve(result); | |||
|
|
601 | return promise; | |||
|
|
602 | } | |||
|
|
603 | ||||
|
|
604 | int pending = promises.Count; | |||
|
|
605 | ||||
|
|
606 | for (int i = 0; i < promises.Count; i++) { | |||
|
|
607 | var dest = i; | |||
|
|
608 | ||||
|
|
609 | promises[i].Then( | |||
|
|
610 | x => { | |||
|
|
611 | result[dest] = x; | |||
|
|
612 | if(Interlocked.Decrement(ref pending) == 0) | |||
|
|
613 | promise.Resolve(result); | |||
|
|
614 | }, | |||
|
|
615 | e => promise.Reject(e) | |||
|
|
616 | ); | |||
|
|
617 | } | |||
|
|
618 | ||||
|
|
619 | promise.Cancelled( | |||
|
|
620 | () => { | |||
|
|
621 | foreach(var d in promises) | |||
|
|
622 | if(d.IsExclusive) | |||
|
|
623 | d.Cancel(); | |||
|
|
624 | } | |||
|
|
625 | ); | |||
|
|
626 | ||||
|
|
627 | return promise; | |||
|
|
628 | } | |||
|
|
629 | ||||
|
|
630 | public static Promise<T> ResultToPromise(T result) { | |||
|
|
631 | var p = new Promise<T>(); | |||
|
|
632 | p.Resolve(result); | |||
|
|
633 | return p; | |||
|
|
634 | } | |||
|
|
635 | ||||
|
|
636 | public static Promise<T> ExceptionToPromise(Exception error) { | |||
|
|
637 | if (error == null) | |||
|
|
638 | throw new ArgumentNullException(); | |||
|
|
639 | ||||
|
|
640 | var p = new Promise<T>(); | |||
|
|
641 | p.Reject(error); | |||
|
|
642 | return p; | |||
|
|
643 | } | |||
|
|
644 | ||||
| 563 | } |
|
645 | } | |
| 564 | } |
|
646 | } | |
| @@ -12,7 +12,7 namespace Implab | |||||
| 12 | /// <remarks> |
|
12 | /// <remarks> | |
| 13 | /// Members of this object are thread safe. |
|
13 | /// Members of this object are thread safe. | |
| 14 | /// </remarks> |
|
14 | /// </remarks> | |
| 15 |
class TaskController: IProgressNotifier, ITaskController |
|
15 | public class TaskController: IProgressNotifier, ITaskController | |
| 16 | { |
|
16 | { | |
| 17 | readonly object m_lock; |
|
17 | readonly object m_lock; | |
| 18 | string m_message; |
|
18 | string m_message; | |
| @@ -22,6 +22,7 namespace Implab | |||||
| 22 |
|
22 | |||
| 23 | bool m_cancelled; |
|
23 | bool m_cancelled; | |
| 24 |
|
24 | |||
|
|
25 | public event EventHandler Cancelled; | |||
| 25 | public event EventHandler<ValueEventArgs<string>> MessageUpdated; |
|
26 | public event EventHandler<ValueEventArgs<string>> MessageUpdated; | |
| 26 | public event EventHandler<ValueEventArgs<float>> ProgressUpdated; |
|
27 | public event EventHandler<ValueEventArgs<float>> ProgressUpdated; | |
| 27 | public event EventHandler<ProgressInitEventArgs> ProgressInit; |
|
28 | public event EventHandler<ProgressInitEventArgs> ProgressInit; | |
| @@ -84,7 +85,7 namespace Implab | |||||
| 84 | } |
|
85 | } | |
| 85 | } |
|
86 | } | |
| 86 |
|
87 | |||
| 87 | public bool Cancelled { |
|
88 | public bool IsCancelled { | |
| 88 | get { |
|
89 | get { | |
| 89 | lock (m_lock) |
|
90 | lock (m_lock) | |
| 90 | return m_cancelled; |
|
91 | return m_cancelled; | |
| @@ -102,6 +103,13 namespace Implab | |||||
| 102 | } |
|
103 | } | |
| 103 | } |
|
104 | } | |
| 104 |
|
105 | |||
|
|
106 | protected virtual void OnCancelled() { | |||
|
|
107 | var temp = Cancelled; | |||
|
|
108 | if (temp != null) { | |||
|
|
109 | temp(this,new EventArgs()); | |||
|
|
110 | } | |||
|
|
111 | } | |||
|
|
112 | ||||
| 105 | protected virtual void OnMessageUpdated() |
|
113 | protected virtual void OnMessageUpdated() | |
| 106 | { |
|
114 | { | |
| 107 | var temp = MessageUpdated; |
|
115 | var temp = MessageUpdated; | |
General Comments 0
You need to be logged in to leave comments.
Login now
