| @@ -0,0 +1,33 | |||||
|
|
1 | using System; | |||
|
|
2 | using System.Collections.Generic; | |||
|
|
3 | using System.Linq; | |||
|
|
4 | using System.Text; | |||
|
|
5 | ||||
|
|
6 | namespace Implab | |||
|
|
7 | { | |||
|
|
8 | public interface IPromise | |||
|
|
9 | { | |||
|
|
10 | /// <summary> | |||
|
|
11 | /// Check whereather the promise has no more than one dependent promise. | |||
|
|
12 | /// </summary> | |||
|
|
13 | bool IsExclusive | |||
|
|
14 | { | |||
|
|
15 | get; | |||
|
|
16 | } | |||
|
|
17 | ||||
|
|
18 | /// <summary> | |||
|
|
19 | /// The current state of the promise. | |||
|
|
20 | /// </summary> | |||
|
|
21 | PromiseState State | |||
|
|
22 | { | |||
|
|
23 | get; | |||
|
|
24 | } | |||
|
|
25 | ||||
|
|
26 | /// <summary> | |||
|
|
27 | /// Tries to cancel the promise or the complete chain. | |||
|
|
28 | /// </summary> | |||
|
|
29 | /// <param name="dependencies">Try to cancel the parent promise is it has the only one child</param> | |||
|
|
30 | /// <returns></returns> | |||
|
|
31 | bool Cancel(bool dependencies); | |||
|
|
32 | } | |||
|
|
33 | } | |||
| @@ -0,0 +1,36 | |||||
|
|
1 | using System; | |||
|
|
2 | using System.Collections.Generic; | |||
|
|
3 | using System.Linq; | |||
|
|
4 | using System.Text; | |||
|
|
5 | ||||
|
|
6 | namespace Implab | |||
|
|
7 | { | |||
|
|
8 | ||||
|
|
9 | public class ProgressInitEventArgs: EventArgs | |||
|
|
10 | { | |||
|
|
11 | public float MaxProgress | |||
|
|
12 | { | |||
|
|
13 | get; | |||
|
|
14 | private set; | |||
|
|
15 | } | |||
|
|
16 | ||||
|
|
17 | public float CurrentProgress | |||
|
|
18 | { | |||
|
|
19 | get; | |||
|
|
20 | private set; | |||
|
|
21 | } | |||
|
|
22 | ||||
|
|
23 | public string Message | |||
|
|
24 | { | |||
|
|
25 | get; | |||
|
|
26 | private set; | |||
|
|
27 | } | |||
|
|
28 | ||||
|
|
29 | public ProgressInitEventArgs(float current, float max, string message) | |||
|
|
30 | { | |||
|
|
31 | this.MaxProgress = max; | |||
|
|
32 | this.CurrentProgress = current; | |||
|
|
33 | this.Message = message; | |||
|
|
34 | } | |||
|
|
35 | } | |||
|
|
36 | } | |||
| @@ -0,0 +1,15 | |||||
|
|
1 | using System; | |||
|
|
2 | using System.Collections.Generic; | |||
|
|
3 | using System.Linq; | |||
|
|
4 | using System.Text; | |||
|
|
5 | ||||
|
|
6 | namespace Implab | |||
|
|
7 | { | |||
|
|
8 | public enum PromiseState | |||
|
|
9 | { | |||
|
|
10 | Unresolved, | |||
|
|
11 | Resolved, | |||
|
|
12 | Cancelled, | |||
|
|
13 | Rejected | |||
|
|
14 | } | |||
|
|
15 | } | |||
| @@ -0,0 +1,113 | |||||
|
|
1 | using System; | |||
|
|
2 | using System.Collections.Generic; | |||
|
|
3 | using System.Linq; | |||
|
|
4 | using System.Text; | |||
|
|
5 | using System.Threading; | |||
|
|
6 | ||||
|
|
7 | namespace Implab | |||
|
|
8 | { | |||
|
|
9 | /// <summary> | |||
|
|
10 | /// This class allows to interact with asyncronuos task. | |||
|
|
11 | /// </summary> | |||
|
|
12 | /// <remarks> | |||
|
|
13 | /// Members of this object are thread safe. | |||
|
|
14 | /// </remarks> | |||
|
|
15 | class TaskController | |||
|
|
16 | { | |||
|
|
17 | object m_lock; | |||
|
|
18 | string m_message; | |||
|
|
19 | bool m_cancelled; | |||
|
|
20 | ||||
|
|
21 | float m_current; | |||
|
|
22 | float m_max; | |||
|
|
23 | ||||
|
|
24 | public event EventHandler<ValueEventArgs<string>> MessageUpdated; | |||
|
|
25 | public event EventHandler<ValueEventArgs<float>> ProgressUpdated; | |||
|
|
26 | public event EventHandler<ProgressInitEventArgs> ProgressInit; | |||
|
|
27 | ||||
|
|
28 | public TaskController() | |||
|
|
29 | { | |||
|
|
30 | m_lock = new Object(); | |||
|
|
31 | } | |||
|
|
32 | ||||
|
|
33 | public string Message | |||
|
|
34 | { | |||
|
|
35 | get | |||
|
|
36 | { | |||
|
|
37 | lock (m_lock) | |||
|
|
38 | return m_message; | |||
|
|
39 | } | |||
|
|
40 | set | |||
|
|
41 | { | |||
|
|
42 | lock (m_lock) | |||
|
|
43 | { | |||
|
|
44 | m_message = value; | |||
|
|
45 | OnMessageUpdated(); | |||
|
|
46 | } | |||
|
|
47 | } | |||
|
|
48 | } | |||
|
|
49 | ||||
|
|
50 | public float CurrentProgress | |||
|
|
51 | { | |||
|
|
52 | get | |||
|
|
53 | { | |||
|
|
54 | lock (m_lock) | |||
|
|
55 | return m_current; | |||
|
|
56 | } | |||
|
|
57 | set | |||
|
|
58 | { | |||
|
|
59 | lock (m_lock) | |||
|
|
60 | { | |||
|
|
61 | var prev = m_current; | |||
|
|
62 | m_current = value; | |||
|
|
63 | if (m_current >= m_max) | |||
|
|
64 | m_current = m_max; | |||
|
|
65 | if (m_current != prev) | |||
|
|
66 | OnProgressUpdated(); | |||
|
|
67 | } | |||
|
|
68 | } | |||
|
|
69 | } | |||
|
|
70 | ||||
|
|
71 | public void InitProgress(float current, float max, string message) | |||
|
|
72 | { | |||
|
|
73 | if (max < 0) | |||
|
|
74 | throw new ArgumentOutOfRangeException("max"); | |||
|
|
75 | if (current < 0 || current > max) | |||
|
|
76 | throw new ArgumentOutOfRangeException("current"); | |||
|
|
77 | ||||
|
|
78 | lock(m_lock) { | |||
|
|
79 | m_current = current; | |||
|
|
80 | m_max = max; | |||
|
|
81 | m_message = message; | |||
|
|
82 | OnProgressInit(); | |||
|
|
83 | } | |||
|
|
84 | } | |||
|
|
85 | ||||
|
|
86 | protected virtual void OnMessageUpdated() | |||
|
|
87 | { | |||
|
|
88 | var temp = MessageUpdated; | |||
|
|
89 | if (temp != null) | |||
|
|
90 | { | |||
|
|
91 | temp(this, new ValueEventArgs<string>(m_message)); | |||
|
|
92 | } | |||
|
|
93 | } | |||
|
|
94 | ||||
|
|
95 | protected virtual void OnProgressUpdated() | |||
|
|
96 | { | |||
|
|
97 | var temp = ProgressUpdated; | |||
|
|
98 | if (temp != null) | |||
|
|
99 | { | |||
|
|
100 | temp(this,new ValueEventArgs<float>(m_current)); | |||
|
|
101 | } | |||
|
|
102 | } | |||
|
|
103 | ||||
|
|
104 | protected virtual void OnProgressInit() | |||
|
|
105 | { | |||
|
|
106 | var temp = ProgressInit; | |||
|
|
107 | if (temp != null) | |||
|
|
108 | { | |||
|
|
109 | temp(this, new ProgressInitEventArgs(m_current,m_max, m_message)); | |||
|
|
110 | } | |||
|
|
111 | } | |||
|
|
112 | } | |||
|
|
113 | } | |||
| @@ -0,0 +1,20 | |||||
|
|
1 | using System; | |||
|
|
2 | using System.Collections.Generic; | |||
|
|
3 | using System.Linq; | |||
|
|
4 | using System.Text; | |||
|
|
5 | ||||
|
|
6 | namespace Implab | |||
|
|
7 | { | |||
|
|
8 | public class ValueEventArgs<T>: EventArgs | |||
|
|
9 | { | |||
|
|
10 | public ValueEventArgs(T value) | |||
|
|
11 | { | |||
|
|
12 | this.Value = value; | |||
|
|
13 | } | |||
|
|
14 | public T Value | |||
|
|
15 | { | |||
|
|
16 | get; | |||
|
|
17 | private set; | |||
|
|
18 | } | |||
|
|
19 | } | |||
|
|
20 | } | |||
| 1 | NO CONTENT: modified file, binary diff hidden |
|
NO CONTENT: modified file, binary diff hidden |
| @@ -32,10 +32,14 | |||||
| 32 | <Reference Include="System" /> |
|
32 | <Reference Include="System" /> | |
| 33 | </ItemGroup> |
|
33 | </ItemGroup> | |
| 34 | <ItemGroup> |
|
34 | <ItemGroup> | |
|
|
35 | <Compile Include="ICancellable.cs" /> | |||
|
|
36 | <Compile Include="TaskController.cs" /> | |||
|
|
37 | <Compile Include="ProgressInitEventArgs.cs" /> | |||
| 35 | <Compile Include="Properties\AssemblyInfo.cs" /> |
|
38 | <Compile Include="Properties\AssemblyInfo.cs" /> | |
| 36 | <Compile Include="Promise.cs" /> |
|
39 | <Compile Include="Promise.cs" /> | |
| 37 | <Compile Include="AsyncPool.cs" /> |
|
40 | <Compile Include="AsyncPool.cs" /> | |
| 38 | <Compile Include="Safe.cs" /> |
|
41 | <Compile Include="Safe.cs" /> | |
|
|
42 | <Compile Include="ValueEventArgs.cs" /> | |||
| 39 | </ItemGroup> |
|
43 | </ItemGroup> | |
| 40 | <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> |
|
44 | <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> | |
| 41 | <ItemGroup> |
|
45 | <ItemGroup> | |
| @@ -48,30 +48,32 namespace Implab { | |||||
| 48 | /// ΡΠΎΠ»ΡΠΊΠΎ ΠΈΠ½ΠΈΡΠΈΠ°ΡΠΎΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΡ ΠΈΠ½Π°ΡΠ΅ ΠΌΠΎΠ³ΡΡ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡΡΡ ΠΏΡΠΎΡΠΈΠ²ΠΎΡΠ΅ΡΠΈΡ. |
|
48 | /// ΡΠΎΠ»ΡΠΊΠΎ ΠΈΠ½ΠΈΡΠΈΠ°ΡΠΎΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΡ ΠΈΠ½Π°ΡΠ΅ ΠΌΠΎΠ³ΡΡ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡΡΡ ΠΏΡΠΎΡΠΈΠ²ΠΎΡΠ΅ΡΠΈΡ. | |
| 49 | /// </para> |
|
49 | /// </para> | |
| 50 | /// </remarks> |
|
50 | /// </remarks> | |
| 51 | public class Promise<T> { |
|
51 | public class Promise<T>: IPromise { | |
| 52 |
|
52 | |||
| 53 | struct ResultHandlerInfo { |
|
53 | struct ResultHandlerInfo { | |
| 54 | public ResultHandler<T> resultHandler; |
|
54 | public ResultHandler<T> resultHandler; | |
| 55 | public ErrorHandler errorHandler; |
|
55 | public ErrorHandler errorHandler; | |
| 56 | } |
|
56 | public Action cancelHandler; | |
| 57 |
|
||||
| 58 | enum State { |
|
|||
| 59 | Unresolved, |
|
|||
| 60 | Resolving, |
|
|||
| 61 | Resolved, |
|
|||
| 62 | Cancelled |
|
|||
| 63 | } |
|
57 | } | |
| 64 |
|
58 | |||
| 65 | LinkedList<ResultHandlerInfo> m_handlersChain = new LinkedList<ResultHandlerInfo>(); |
|
59 | LinkedList<ResultHandlerInfo> m_handlersChain = new LinkedList<ResultHandlerInfo>(); | |
| 66 | State m_state; |
|
60 | PromiseState m_state; | |
| 67 | bool m_cancellable; |
|
61 | bool m_cancellable; | |
| 68 | T m_result; |
|
62 | T m_result; | |
| 69 | Exception m_error; |
|
63 | Exception m_error; | |
|
|
64 | IPromise m_parent; | |||
|
|
65 | int m_childrenCount; | |||
| 70 |
|
66 | |||
| 71 | public Promise() { |
|
67 | public Promise() { | |
| 72 | m_cancellable = true; |
|
68 | m_cancellable = true; | |
| 73 | } |
|
69 | } | |
| 74 |
|
70 | |||
|
|
71 | public Promise(IPromise parent, bool cancellable) | |||
|
|
72 | { | |||
|
|
73 | m_cancellable = cancellable; | |||
|
|
74 | m_parent = parent; | |||
|
|
75 | } | |||
|
|
76 | ||||
| 75 | /// <summary> |
|
77 | /// <summary> | |
| 76 | /// Π‘ΠΎΠ±ΡΡΠΈΠ΅, Π²ΠΎΠ·Π½ΠΈΠΊΠ°ΡΡΠ΅Π΅ ΠΏΡΠΈ ΠΎΡΠΌΠ΅Π½Π΅ Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΠΎΠΉ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ. |
|
78 | /// Π‘ΠΎΠ±ΡΡΠΈΠ΅, Π²ΠΎΠ·Π½ΠΈΠΊΠ°ΡΡΠ΅Π΅ ΠΏΡΠΈ ΠΎΡΠΌΠ΅Π½Π΅ Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΠΎΠΉ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ. | |
| 77 | /// </summary> |
|
79 | /// </summary> | |
| @@ -87,12 +89,12 namespace Implab { | |||||
| 87 | /// <exception cref="InvalidOperationException">ΠΠ°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ ΡΠΆΠ΅ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception> |
|
89 | /// <exception cref="InvalidOperationException">ΠΠ°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ ΡΠΆΠ΅ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception> | |
| 88 | public void Resolve(T result) { |
|
90 | public void Resolve(T result) { | |
| 89 | lock (this) { |
|
91 | lock (this) { | |
| 90 | if (m_state == State.Cancelled) |
|
92 | if (m_state == PromiseState.Cancelled) | |
| 91 | return; |
|
93 | return; | |
| 92 | if (m_state != State.Unresolved) |
|
94 | if (m_state != PromiseState.Unresolved) | |
| 93 | throw new InvalidOperationException("The promise is already resolved"); |
|
95 | throw new InvalidOperationException("The promise is already resolved"); | |
| 94 | m_result = result; |
|
96 | m_result = result; | |
| 95 |
m_state = State.Resolv |
|
97 | m_state = PromiseState.Resolved; | |
| 96 | } |
|
98 | } | |
| 97 |
|
99 | |||
| 98 | ResultHandlerInfo handler; |
|
100 | ResultHandlerInfo handler; | |
| @@ -107,12 +109,12 namespace Implab { | |||||
| 107 | /// <exception cref="InvalidOperationException">ΠΠ°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ ΡΠΆΠ΅ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception> |
|
109 | /// <exception cref="InvalidOperationException">ΠΠ°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ ΡΠΆΠ΅ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception> | |
| 108 | public void Reject(Exception error) { |
|
110 | public void Reject(Exception error) { | |
| 109 | lock (this) { |
|
111 | lock (this) { | |
| 110 | if (m_state == State.Cancelled) |
|
112 | if (m_state == PromiseState.Cancelled) | |
| 111 | return; |
|
113 | return; | |
| 112 | if (m_state != State.Unresolved) |
|
114 | if (m_state != PromiseState.Unresolved) | |
| 113 | throw new InvalidOperationException("The promise is already resolved"); |
|
115 | throw new InvalidOperationException("The promise is already resolved"); | |
| 114 | m_error = error; |
|
116 | m_error = error; | |
| 115 |
m_state = State.Re |
|
117 | m_state = PromiseState.Rejected; | |
| 116 | } |
|
118 | } | |
| 117 |
|
119 | |||
| 118 | ResultHandlerInfo handler; |
|
120 | ResultHandlerInfo handler; | |
| @@ -126,8 +128,9 namespace Implab { | |||||
| 126 | /// <returns><c>true</c> ΠΠΏΠ΅ΡΠ°ΡΠΈΡ Π±ΡΠ»Π° ΠΎΡΠΌΠ΅Π½Π΅Π½Π°, ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ Π½Π΅ Π±ΡΠ΄ΡΡ Π²ΡΠ·Π²Π°Π½Ρ.<c>false</c> ΠΎΡΠΌΠ΅Π½Π° Π½Π΅ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π°, ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ ΡΠΆΠ΅ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΈ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ ΠΎΡΡΠ°Π±ΠΎΡΠ°Π»ΠΈ.</returns> |
|
128 | /// <returns><c>true</c> ΠΠΏΠ΅ΡΠ°ΡΠΈΡ Π±ΡΠ»Π° ΠΎΡΠΌΠ΅Π½Π΅Π½Π°, ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ Π½Π΅ Π±ΡΠ΄ΡΡ Π²ΡΠ·Π²Π°Π½Ρ.<c>false</c> ΠΎΡΠΌΠ΅Π½Π° Π½Π΅ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π°, ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ ΡΠΆΠ΅ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΈ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ ΠΎΡΡΠ°Π±ΠΎΡΠ°Π»ΠΈ.</returns> | |
| 127 | public bool Cancel() { |
|
129 | public bool Cancel() { | |
| 128 | lock (this) { |
|
130 | lock (this) { | |
| 129 |
if (m_state == State.Unresolved && m_cancellable) |
|
131 | if (m_state == PromiseState.Unresolved && m_cancellable) | |
| 130 | m_state = State.Cancelled; |
|
132 | { | |
|
|
133 | m_state = PromiseState.Cancelled; | |||
| 131 | EventHandler temp = Cancelled; |
|
134 | EventHandler temp = Cancelled; | |
| 132 |
|
135 | |||
| 133 | if (temp != null) |
|
136 | if (temp != null) | |
| @@ -348,14 +351,13 namespace Implab { | |||||
| 348 | handler = default(ResultHandlerInfo); |
|
351 | handler = default(ResultHandlerInfo); | |
| 349 |
|
352 | |||
| 350 | lock (this) { |
|
353 | lock (this) { | |
| 351 |
Debug.Assert(m_state |
|
354 | Debug.Assert(m_state != PromiseState.Unresolved); | |
| 352 |
|
355 | |||
| 353 | if (m_handlersChain.Count > 0) { |
|
356 | if (m_handlersChain.Count > 0) { | |
| 354 | handler = m_handlersChain.First.Value; |
|
357 | handler = m_handlersChain.First.Value; | |
| 355 | m_handlersChain.RemoveFirst(); |
|
358 | m_handlersChain.RemoveFirst(); | |
| 356 | return true; |
|
359 | return true; | |
| 357 | } else { |
|
360 | } else { | |
| 358 | m_state = State.Resolved; |
|
|||
| 359 | return false; |
|
361 | return false; | |
| 360 | } |
|
362 | } | |
| 361 | } |
|
363 | } | |
| @@ -365,7 +367,7 namespace Implab { | |||||
| 365 | bool invokeRequired = false; |
|
367 | bool invokeRequired = false; | |
| 366 |
|
368 | |||
| 367 | lock (this) { |
|
369 | lock (this) { | |
| 368 |
if (m_state |
|
370 | if (m_state == PromiseState.Unresolved) | |
| 369 | m_handlersChain.AddLast(handler); |
|
371 | m_handlersChain.AddLast(handler); | |
| 370 | else |
|
372 | else | |
| 371 | invokeRequired = true; |
|
373 | invokeRequired = true; | |
General Comments 0
You need to be logged in to leave comments.
Login now
