##// END OF EJS Templates
refactoring
cin -
r25:9bf5b23650c9 default
parent child
Show More
@@ -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: ICancellable
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 }
@@ -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 ResolvedState = 2;
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,11 +145,14 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(ResolvedState);
148 CompleteTransit(SucceededState);
143 OnStateChanged();
149 OnStateChanged();
144 } else if (m_state != CancelledState)
150 } else {
151 WaitTransition();
152 if (m_state != CancelledState)
145 throw new InvalidOperationException("The promise is already resolved");
153 throw new InvalidOperationException("The promise is already resolved");
146 }
154 }
155 }
147
156
148 /// <summary>
157 /// <summary>
149 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ошибкС
158 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ошибкС
@@ -160,9 +169,12 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 {
173 WaitTransition();
174 if (m_state == SucceededState)
164 throw new InvalidOperationException("The promise is already resolved");
175 throw new InvalidOperationException("The promise is already resolved");
165 }
176 }
177 }
166
178
167 /// <summary>
179 /// <summary>
168 /// ΠžΡ‚ΠΌΠ΅Π½ΡΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.
180 /// ΠžΡ‚ΠΌΠ΅Π½ΡΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.
@@ -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(x);
257 medium.Reject(e);
258 }
243 };
259 };
244 else
260 else
245 errorHandler = medium.Reject;
261 errorHandler = medium.Reject;
@@ -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 ResolvedState:
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 ResolvedState:
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, ICancellable
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