@@ -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