##// END OF EJS Templates
Refactoring of the IPromise<T> interface...
cin -
r76:c761fc982e1d v2
parent child
Show More
@@ -1,87 +1,41
1 using System;
1 using System;
2 using System.Windows.Forms;
2 using System.Windows.Forms;
3 using System.Threading;
3 using System.Threading;
4
4
5 namespace Implab.Fx
5 namespace Implab.Fx
6 {
6 {
7 public static class PromiseHelpers
7 public static class PromiseHelpers
8 {
8 {
9 /// <summary>
9 /// <summary>
10 /// ΠŸΠ΅Ρ€Π΅Π½Π°ΠΏΡ€Π°Π²Π»ΡΠ΅Ρ‚ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ обСщания Π² ΠΏΠΎΡ‚ΠΎΠΊ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠ³ΠΎ элСмСнта управлСния.
10 /// ΠŸΠ΅Ρ€Π΅Π½Π°ΠΏΡ€Π°Π²Π»ΡΠ΅Ρ‚ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ обСщания Π² ΠΏΠΎΡ‚ΠΎΠΊ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠ³ΠΎ элСмСнта управлСния.
11 /// </summary>
11 /// </summary>
12 /// <typeparam name="T">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° обСщания</typeparam>
12 /// <typeparam name="T">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° обСщания</typeparam>
13 /// <param name="that">Π˜ΡΡ…ΠΎΠ΄Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅</param>
13 /// <param name="that">Π˜ΡΡ…ΠΎΠ΄Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅</param>
14 /// <param name="ctl">Π­Π»Π΅ΠΌΠ΅Π½Ρ‚ управлСния</param>
14 /// <param name="ctl">Π­Π»Π΅ΠΌΠ΅Π½Ρ‚ управлСния</param>
15 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Ρ‹ Π² ΠΏΠΎΡ‚ΠΎΠΊΠ΅ элСмСнта управлСния.</returns>
15 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Ρ‹ Π² ΠΏΠΎΡ‚ΠΎΠΊΠ΅ элСмСнта управлСния.</returns>
16 /// <exception cref="ArgumentNullException">ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ <c>null</c>.</exception>
16 /// <exception cref="ArgumentNullException">ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ <c>null</c>.</exception>
17 /// <example>
17 /// <example>
18 /// client
18 /// client
19 /// .Get("description.txt") // returns a promise
19 /// .Get("description.txt") // returns a promise
20 /// .DirectToControl(m_ctl) // handle the promise in the thread of the control
20 /// .DispatchToControl(m_ctl) // handle the promise in the thread of the control
21 /// .Then(
21 /// .Then(
22 /// description => m_ctl.Text = description // now it's safe
22 /// description => m_ctl.Text = description // now it's safe
23 /// )
23 /// )
24 /// </example>
24 /// </example>
25 public static Promise<T> DispatchToControl<T>(this Promise<T> that, Control ctl)
25 public static IPromise<T> DispatchToControl<T>(this IPromise<T> that, Control ctl)
26 {
26 {
27 if (that == null)
27 Safe.ArgumentNotNull(that, "that");
28 throw new ArgumentNullException("that");
28 Safe.ArgumentNotNull(ctl, "ctl");
29 if (ctl == null)
30 throw new ArgumentNullException("ctl");
31
29
32 var directed = new ControlBoundPromise<T>(ctl,that,true);
30 var directed = new ControlBoundPromise<T>(ctl,that,true);
33
31
34 that.Then(
32 that.Last(
35 directed.Resolve,
33 directed.Resolve,
36 err =>
34 directed.Reject,
37 {
35 directed.Cancel
38 directed.Reject(err);
39 return default(T);
40 }
41 );
36 );
42
37
43 return directed;
38 return directed;
44 }
39 }
45
46 /// <summary>
47 /// НаправляСт ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ обСщания Π² Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ, Ссли Ρƒ Π½Π΅Π³ΠΎ сущСствуСт контСкст синхронизации.
48 /// </summary>
49 /// <typeparam name="T">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° обСщания.</typeparam>
50 /// <param name="that">ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π½ΡƒΠΆΠ½ΠΎ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ ΠΏΠΎΡ‚ΠΎΠΊΠ΅.</param>
51 /// <returns>ΠŸΠ΅Ρ€Π΅Π½Π°ΠΏΡ€Π°Π²Π»Π΅Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅.</returns>
52 public static Promise<T> DispatchToCurrentThread<T>(this Promise<T> that)
53 {
54 var sync = SynchronizationContext.Current;
55 if (sync == null)
56 throw new InvalidOperationException("The current thread doesn't have a syncronization context");
57 return DispatchToSyncContext(that, sync);
58 }
59
60 /// <summary>
61 /// НаправляСт ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ обСщания Π² ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΉ контСкст синхронизации.
62 /// </summary>
63 /// <typeparam name="T">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° обСщания.</typeparam>
64 /// <param name="that">ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ трСбуСтся ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΌ контСкстС синхронизации.</param>
65 /// <param name="sync">ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ синхронизации Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ Π½Π°ΠΏΡ€Π°Π²Π»Π΅Π½ΠΎ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅.</param>
66 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒΡΡ Π² ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΌ контСкстС.</returns>
67 public static Promise<T> DispatchToSyncContext<T>(this Promise<T> that, SynchronizationContext sync)
68 {
69 if (that == null)
70 throw new ArgumentNullException("that");
71 if (sync == null)
72 throw new ArgumentNullException("sync");
73
74 var d = new Promise<T>();
75
76 that.Then(
77 res => sync.Post(state => d.Resolve(res), null),
78 err => {
79 sync.Post(state => d.Reject(err), null);
80 return default(T);
81 }
82 );
83
84 return d;
85 }
40 }
86 }
41 }
87 }
@@ -1,36 +1,35
1 using System.Reflection;
1 using System.Reflection;
2 using System.Runtime.CompilerServices;
2 using System.Runtime.CompilerServices;
3 using System.Runtime.InteropServices;
3 using System.Runtime.InteropServices;
4
4
5 // General Information about an assembly is controlled through the following
5 // General Information about an assembly is controlled through the following
6 // set of attributes. Change these attribute values to modify the information
6 // set of attributes. Change these attribute values to modify the information
7 // associated with an assembly.
7 // associated with an assembly.
8 [assembly: AssemblyTitle("Implab.Fx")]
8 [assembly: AssemblyTitle("Implab.Fx")]
9 [assembly: AssemblyDescription("")]
9 [assembly: AssemblyDescription("")]
10 [assembly: AssemblyConfiguration("")]
10 [assembly: AssemblyConfiguration("")]
11 [assembly: AssemblyCompany("")]
11 [assembly: AssemblyCompany("")]
12 [assembly: AssemblyProduct("Implab.Fx")]
12 [assembly: AssemblyProduct("Implab.Fx")]
13 [assembly: AssemblyCopyright("Copyright Β© 2013")]
13 [assembly: AssemblyCopyright("Copyright Β© 2013")]
14 [assembly: AssemblyTrademark("")]
14 [assembly: AssemblyTrademark("")]
15 [assembly: AssemblyCulture("")]
15 [assembly: AssemblyCulture("")]
16
16
17 // Setting ComVisible to false makes the types in this assembly not visible
17 // Setting ComVisible to false makes the types in this assembly not visible
18 // to COM components. If you need to access a type in this assembly from
18 // to COM components. If you need to access a type in this assembly from
19 // COM, set the ComVisible attribute to true on that type.
19 // COM, set the ComVisible attribute to true on that type.
20 [assembly: ComVisible(false)]
20 [assembly: ComVisible(false)]
21
21
22 // The following GUID is for the ID of the typelib if this project is exposed to COM
22 // The following GUID is for the ID of the typelib if this project is exposed to COM
23 [assembly: Guid("d239c29f-98e2-4942-9569-554a8511d07b")]
23 [assembly: Guid("d239c29f-98e2-4942-9569-554a8511d07b")]
24
24
25 // Version information for an assembly consists of the following four values:
25 // Version information for an assembly consists of the following four values:
26 //
26 //
27 // Major Version
27 // Major Version
28 // Minor Version
28 // Minor Version
29 // Build Number
29 // Build Number
30 // Revision
30 // Revision
31 //
31 //
32 // You can specify all the values or you can default the Build and Revision Numbers
32 // You can specify all the values or you can default the Build and Revision Numbers
33 // by using the '*' as shown below:
33 // by using the '*' as shown below:
34 // [assembly: AssemblyVersion("1.0.*")]
34 // [assembly: AssemblyVersion("1.0.*")]
35 [assembly: AssemblyVersion("1.0.0.0")]
35 [assembly: AssemblyVersion("2.0.*")]
36 [assembly: AssemblyFileVersion("1.0.0.0")]
@@ -1,392 +1,423
1 using System;
1 using System;
2 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using Microsoft.VisualStudio.TestTools.UnitTesting;
3 using System.Reflection;
3 using System.Reflection;
4 using System.Threading;
4 using System.Threading;
5 using Implab.Parallels;
5 using Implab.Parallels;
6
6
7 namespace Implab.Test {
7 namespace Implab.Test {
8 [TestClass]
8 [TestClass]
9 public class AsyncTests {
9 public class AsyncTests {
10 [TestMethod]
10 [TestMethod]
11 public void ResolveTest() {
11 public void ResolveTest() {
12 int res = -1;
12 int res = -1;
13 var p = new Promise<int>();
13 var p = new Promise<int>();
14 p.Then(x => res = x);
14 p.Then(x => res = x);
15 p.Resolve(100);
15 p.Resolve(100);
16
16
17 Assert.AreEqual(100, res);
17 Assert.AreEqual(100, res);
18 }
18 }
19
19
20 [TestMethod]
20 [TestMethod]
21 public void RejectTest() {
21 public void RejectTest() {
22 int res = -1;
22 int res = -1;
23 Exception err = null;
23 Exception err = null;
24
24
25 var p = new Promise<int>();
25 var p = new Promise<int>();
26 p.Then(
26 p.Then(
27 x => res = x,
27 x => res = x,
28 e => {
28 e => {
29 err = e;
29 err = e;
30 return -2;
30 return -2;
31 }
31 }
32 );
32 );
33 p.Reject(new ApplicationException("error"));
33 p.Reject(new ApplicationException("error"));
34
34
35 Assert.AreEqual(res, -1);
35 Assert.AreEqual(res, -1);
36 Assert.AreEqual(err.Message, "error");
36 Assert.AreEqual(err.Message, "error");
37
37
38 }
38 }
39
39
40 [TestMethod]
40 [TestMethod]
41 public void CancelExceptionTest() {
42 var p = new Promise<bool>();
43 p.Cancel();
44
45 var p2 = p.Cancelled(() => {
46 throw new ApplicationException("CANCELLED");
47 });
48
49 try {
50 p2.Join();
51 Assert.Fail();
52 } catch (ApplicationException err) {
53 Assert.AreEqual("CANCELLED", err.InnerException.Message);
54 }
55
56 }
57
58 [TestMethod]
59 public void ContinueOnCancelTest() {
60 var p = new Promise<bool>();
61 p.Cancel();
62
63 var p2 = p
64 .Cancelled(() => {
65 throw new ApplicationException("CANCELLED");
66 })
67 .Error(e => true);
68
69 Assert.AreEqual(true, p2.Join());
70 }
71
72 [TestMethod]
41 public void JoinSuccessTest() {
73 public void JoinSuccessTest() {
42 var p = new Promise<int>();
74 var p = new Promise<int>();
43 p.Resolve(100);
75 p.Resolve(100);
44 Assert.AreEqual(p.Join(), 100);
76 Assert.AreEqual(p.Join(), 100);
45 }
77 }
46
78
47 [TestMethod]
79 [TestMethod]
48 public void JoinFailTest() {
80 public void JoinFailTest() {
49 var p = new Promise<int>();
81 var p = new Promise<int>();
50 p.Reject(new ApplicationException("failed"));
82 p.Reject(new ApplicationException("failed"));
51
83
52 try {
84 try {
53 p.Join();
85 p.Join();
54 throw new ApplicationException("WRONG!");
86 throw new ApplicationException("WRONG!");
55 } catch (TargetInvocationException err) {
87 } catch (TargetInvocationException err) {
56 Assert.AreEqual(err.InnerException.Message, "failed");
88 Assert.AreEqual(err.InnerException.Message, "failed");
57 } catch {
89 } catch {
58 Assert.Fail("Got wrong excaption");
90 Assert.Fail("Got wrong excaption");
59 }
91 }
60 }
92 }
61
93
62 [TestMethod]
94 [TestMethod]
63 public void MapTest() {
95 public void MapTest() {
64 var p = new Promise<int>();
96 var p = new Promise<int>();
65
97
66 var p2 = p.Map(x => x.ToString());
98 var p2 = p.Then(x => x.ToString());
67 p.Resolve(100);
99 p.Resolve(100);
68
100
69 Assert.AreEqual(p2.Join(), "100");
101 Assert.AreEqual(p2.Join(), "100");
70 }
102 }
71
103
72 [TestMethod]
104 [TestMethod]
73 public void FixErrorTest() {
105 public void FixErrorTest() {
74 var p = new Promise<int>();
106 var p = new Promise<int>();
75
107
76 var p2 = p.Error(e => 101);
108 var p2 = p.Error(e => 101);
77
109
78 p.Reject(new Exception());
110 p.Reject(new Exception());
79
111
80 Assert.AreEqual(p2.Join(), 101);
112 Assert.AreEqual(p2.Join(), 101);
81 }
113 }
82
114
83 [TestMethod]
115 [TestMethod]
84 public void ChainTest() {
116 public void ChainTest() {
85 var p1 = new Promise<int>();
117 var p1 = new Promise<int>();
86
118
87 var p3 = p1.Chain(x => {
119 var p3 = p1.Chain(x => {
88 var p2 = new Promise<string>();
120 var p2 = new Promise<string>();
89 p2.Resolve(x.ToString());
121 p2.Resolve(x.ToString());
90 return p2;
122 return p2;
91 });
123 });
92
124
93 p1.Resolve(100);
125 p1.Resolve(100);
94
126
95 Assert.AreEqual(p3.Join(), "100");
127 Assert.AreEqual(p3.Join(), "100");
96 }
128 }
97
129
98 [TestMethod]
130 [TestMethod]
99 public void PoolTest() {
131 public void PoolTest() {
100 var pid = Thread.CurrentThread.ManagedThreadId;
132 var pid = Thread.CurrentThread.ManagedThreadId;
101 var p = AsyncPool.Invoke(() => Thread.CurrentThread.ManagedThreadId);
133 var p = AsyncPool.Invoke(() => Thread.CurrentThread.ManagedThreadId);
102
134
103 Assert.AreNotEqual(pid, p.Join());
135 Assert.AreNotEqual(pid, p.Join());
104 }
136 }
105
137
106 [TestMethod]
138 [TestMethod]
107 public void WorkerPoolSizeTest() {
139 public void WorkerPoolSizeTest() {
108 var pool = new WorkerPool(5, 10, 0);
140 var pool = new WorkerPool(5, 10, 0);
109
141
110 Assert.AreEqual(5, pool.PoolSize);
142 Assert.AreEqual(5, pool.PoolSize);
111
143
112 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
144 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
113 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
145 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
114 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
146 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
115
147
116 Assert.AreEqual(5, pool.PoolSize);
148 Assert.AreEqual(5, pool.PoolSize);
117
149
118 for (int i = 0; i < 100; i++)
150 for (int i = 0; i < 100; i++)
119 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
151 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
120 Thread.Sleep(200);
152 Thread.Sleep(200);
121 Assert.AreEqual(10, pool.PoolSize);
153 Assert.AreEqual(10, pool.PoolSize);
122
154
123 pool.Dispose();
155 pool.Dispose();
124 }
156 }
125
157
126 [TestMethod]
158 [TestMethod]
127 public void WorkerPoolCorrectTest() {
159 public void WorkerPoolCorrectTest() {
128 var pool = new WorkerPool(0,1000,100);
160 var pool = new WorkerPool(0,1000,100);
129
161
130 int iterations = 1000;
162 int iterations = 1000;
131 int pending = iterations;
163 int pending = iterations;
132 var stop = new ManualResetEvent(false);
164 var stop = new ManualResetEvent(false);
133
165
134 var count = 0;
166 var count = 0;
135 for (int i = 0; i < iterations; i++) {
167 for (int i = 0; i < iterations; i++) {
136 pool
168 pool
137 .Invoke(() => 1)
169 .Invoke(() => 1)
138 .Then(x => Interlocked.Add(ref count, x))
170 .Then(x => Interlocked.Add(ref count, x))
139 .Then(x => Math.Log10(x))
171 .Then(x => Math.Log10(x))
140 .Anyway(() => {
172 .Anyway(() => {
141 Interlocked.Decrement(ref pending);
173 Interlocked.Decrement(ref pending);
142 if (pending == 0)
174 if (pending == 0)
143 stop.Set();
175 stop.Set();
144 });
176 });
145 }
177 }
146
178
147 stop.WaitOne();
179 stop.WaitOne();
148
180
149 Assert.AreEqual(iterations, count);
181 Assert.AreEqual(iterations, count);
150 Console.WriteLine("Max threads: {0}", pool.MaxRunningThreads);
182 Console.WriteLine("Max threads: {0}", pool.MaxRunningThreads);
151 pool.Dispose();
183 pool.Dispose();
152
184
153 }
185 }
154
186
155 [TestMethod]
187 [TestMethod]
156 public void WorkerPoolDisposeTest() {
188 public void WorkerPoolDisposeTest() {
157 var pool = new WorkerPool(5, 20);
189 var pool = new WorkerPool(5, 20);
158 Assert.AreEqual(5, pool.PoolSize);
190 Assert.AreEqual(5, pool.PoolSize);
159 pool.Dispose();
191 pool.Dispose();
160 Thread.Sleep(500);
192 Thread.Sleep(500);
161 Assert.AreEqual(0, pool.PoolSize);
193 Assert.AreEqual(0, pool.PoolSize);
162 pool.Dispose();
194 pool.Dispose();
163 }
195 }
164
196
165 [TestMethod]
197 [TestMethod]
166 public void MTQueueTest() {
198 public void MTQueueTest() {
167 var queue = new MTQueue<int>();
199 var queue = new MTQueue<int>();
168 int res;
200 int res;
169
201
170 queue.Enqueue(10);
202 queue.Enqueue(10);
171 Assert.IsTrue(queue.TryDequeue(out res));
203 Assert.IsTrue(queue.TryDequeue(out res));
172 Assert.AreEqual(10, res);
204 Assert.AreEqual(10, res);
173 Assert.IsFalse(queue.TryDequeue(out res));
205 Assert.IsFalse(queue.TryDequeue(out res));
174
206
175 for (int i = 0; i < 1000; i++)
207 for (int i = 0; i < 1000; i++)
176 queue.Enqueue(i);
208 queue.Enqueue(i);
177
209
178 for (int i = 0; i < 1000; i++) {
210 for (int i = 0; i < 1000; i++) {
179 queue.TryDequeue(out res);
211 queue.TryDequeue(out res);
180 Assert.AreEqual(i, res);
212 Assert.AreEqual(i, res);
181 }
213 }
182
214
183 int writers = 0;
215 int writers = 0;
184 int readers = 0;
216 int readers = 0;
185 var stop = new ManualResetEvent(false);
217 var stop = new ManualResetEvent(false);
186 int total = 0;
218 int total = 0;
187
219
188 int itemsPerWriter = 1000;
220 int itemsPerWriter = 10000;
189 int writersCount = 3;
221 int writersCount = 10;
190
222
191 for (int i = 0; i < writersCount; i++) {
223 for (int i = 0; i < writersCount; i++) {
192 Interlocked.Increment(ref writers);
224 Interlocked.Increment(ref writers);
193 var wn = i;
225 var wn = i;
194 AsyncPool
226 AsyncPool
195 .InvokeNewThread(() => {
227 .InvokeNewThread(() => {
196 for (int ii = 0; ii < itemsPerWriter; ii++) {
228 for (int ii = 0; ii < itemsPerWriter; ii++) {
197 queue.Enqueue(1);
229 queue.Enqueue(1);
198 }
230 }
199 return 1;
231 return 1;
200 })
232 })
201 .Anyway(() => Interlocked.Decrement(ref writers));
233 .Anyway(() => Interlocked.Decrement(ref writers));
202 }
234 }
203
235
204 for (int i = 0; i < 10; i++) {
236 for (int i = 0; i < 10; i++) {
205 Interlocked.Increment(ref readers);
237 Interlocked.Increment(ref readers);
206 var wn = i;
238 var wn = i;
207 AsyncPool
239 AsyncPool
208 .InvokeNewThread(() => {
240 .InvokeNewThread(() => {
209 int t;
241 int t;
210 do {
242 do {
211 while (queue.TryDequeue(out t))
243 while (queue.TryDequeue(out t))
212 Interlocked.Add(ref total, t);
244 Interlocked.Add(ref total, t);
213 } while (writers > 0);
245 } while (writers > 0);
214 return 1;
246 return 1;
215 })
247 })
216 .Anyway(() => {
248 .Anyway(() => {
217 Interlocked.Decrement(ref readers);
249 Interlocked.Decrement(ref readers);
218 if (readers == 0)
250 if (readers == 0)
219 stop.Set();
251 stop.Set();
220 });
252 });
221 }
253 }
222
254
223 stop.WaitOne();
255 stop.WaitOne();
224
256
225 Assert.AreEqual(itemsPerWriter * writersCount, total);
257 Assert.AreEqual(itemsPerWriter * writersCount, total);
226 }
258 }
227
259
228 [TestMethod]
260 [TestMethod]
229 public void ParallelMapTest() {
261 public void ParallelMapTest() {
230
262
231 int count = 100000;
263 int count = 100000;
232
264
233 double[] args = new double[count];
265 double[] args = new double[count];
234 var rand = new Random();
266 var rand = new Random();
235
267
236 for (int i = 0; i < count; i++)
268 for (int i = 0; i < count; i++)
237 args[i] = rand.NextDouble();
269 args[i] = rand.NextDouble();
238
270
239 var t = Environment.TickCount;
271 var t = Environment.TickCount;
240 var res = args.ParallelMap(x => Math.Sin(x*x), 4).Join();
272 var res = args.ParallelMap(x => Math.Sin(x*x), 4).Join();
241
273
242 Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t);
274 Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t);
243
275
244 t = Environment.TickCount;
276 t = Environment.TickCount;
245 for (int i = 0; i < count; i++)
277 for (int i = 0; i < count; i++)
246 Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]);
278 Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]);
247 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
279 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
248 }
280 }
249
281
250 [TestMethod]
282 [TestMethod]
251 public void ChainedMapTest() {
283 public void ChainedMapTest() {
252
284
253 using (var pool = new WorkerPool(0,100,100)) {
285 using (var pool = new WorkerPool(0,100,100)) {
254 int count = 10000;
286 int count = 10000;
255
287
256 double[] args = new double[count];
288 double[] args = new double[count];
257 var rand = new Random();
289 var rand = new Random();
258
290
259 for (int i = 0; i < count; i++)
291 for (int i = 0; i < count; i++)
260 args[i] = rand.NextDouble();
292 args[i] = rand.NextDouble();
261
293
262 var t = Environment.TickCount;
294 var t = Environment.TickCount;
263 var res = args
295 var res = args
264 .ChainedMap(
296 .ChainedMap(
265 x => pool.Invoke(
297 x => pool.Invoke(
266 () => Math.Sin(x * x)
298 () => Math.Sin(x * x)
267 ),
299 ),
268 4
300 4
269 )
301 )
270 .Join();
302 .Join();
271
303
272 Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t);
304 Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t);
273
305
274 t = Environment.TickCount;
306 t = Environment.TickCount;
275 for (int i = 0; i < count; i++)
307 for (int i = 0; i < count; i++)
276 Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]);
308 Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]);
277 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
309 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
278 Console.WriteLine("Max workers: {0}", pool.MaxRunningThreads);
310 Console.WriteLine("Max workers: {0}", pool.MaxRunningThreads);
279 }
311 }
280 }
312 }
281
313
282 [TestMethod]
314 [TestMethod]
283 public void ParallelForEachTest() {
315 public void ParallelForEachTest() {
284
316
285 int count = 100000;
317 int count = 100000;
286
318
287 int[] args = new int[count];
319 int[] args = new int[count];
288 var rand = new Random();
320 var rand = new Random();
289
321
290 for (int i = 0; i < count; i++)
322 for (int i = 0; i < count; i++)
291 args[i] = (int)(rand.NextDouble() * 100);
323 args[i] = (int)(rand.NextDouble() * 100);
292
324
293 int result = 0;
325 int result = 0;
294
326
295 var t = Environment.TickCount;
327 var t = Environment.TickCount;
296 args.ParallelForEach(x => Interlocked.Add(ref result, x), 4).Join();
328 args.ParallelForEach(x => Interlocked.Add(ref result, x), 4).Join();
297
329
298 Console.WriteLine("Iteration complete in {0} ms, result: {1}", Environment.TickCount - t, result);
330 Console.WriteLine("Iteration complete in {0} ms, result: {1}", Environment.TickCount - t, result);
299
331
300 int result2 = 0;
332 int result2 = 0;
301
333
302 t = Environment.TickCount;
334 t = Environment.TickCount;
303 for (int i = 0; i < count; i++)
335 for (int i = 0; i < count; i++)
304 result2 += args[i];
336 result2 += args[i];
305 Assert.AreEqual(result2, result);
337 Assert.AreEqual(result2, result);
306 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
338 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
307 }
339 }
308
340
309 [TestMethod]
341 [TestMethod]
310 public void ComplexCase1Test() {
342 public void ComplexCase1Test() {
311 var flags = new bool[3];
343 var flags = new bool[3];
312
344
313 // op1 (aync 200ms) => op2 (async 200ms) => op3 (sync map)
345 // op1 (aync 200ms) => op2 (async 200ms) => op3 (sync map)
314
346
315 var p = PromiseHelper
347 var p = PromiseHelper
316 .Sleep(200, "Alan")
348 .Sleep(200, "Alan")
317 .Cancelled(() => flags[0] = true)
349 .Cancelled(() => flags[0] = true)
318 .Chain(x =>
350 .Chain(x =>
319 PromiseHelper
351 PromiseHelper
320 .Sleep(200, "Hi, " + x)
352 .Sleep(200, "Hi, " + x)
321 .Map(y => y)
353 .Then(y => y)
322 .Cancelled(() => flags[1] = true)
354 .Cancelled(() => flags[1] = true)
323 )
355 )
324 .Cancelled(() => flags[2] = true);
356 .Cancelled(() => flags[2] = true);
325 Thread.Sleep(300);
357 Thread.Sleep(300);
326 p.Cancel();
358 p.Cancel();
327 try {
359 try {
328 Assert.AreEqual(p.Join(), "Hi, Alan");
360 Assert.AreEqual(p.Join(), "Hi, Alan");
329 Assert.Fail("Shouldn't get here");
361 Assert.Fail("Shouldn't get here");
330 } catch (OperationCanceledException) {
362 } catch (OperationCanceledException) {
331 }
363 }
332
364
333 Assert.IsFalse(flags[0]);
365 Assert.IsFalse(flags[0]);
334 Assert.IsTrue(flags[1]);
366 Assert.IsTrue(flags[1]);
335 Assert.IsTrue(flags[2]);
367 Assert.IsTrue(flags[2]);
336 }
368 }
337
369
338 [TestMethod]
370 [TestMethod]
339 public void ChainedCancel1Test() {
371 public void ChainedCancel1Test() {
340 // ΠΏΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ сцСплСнной асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ всС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ
372 // ΠΏΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ сцСплСнной асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ всС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ
341 // Π·Π°Π²Π΅Ρ€ΡˆΠ°Ρ‚ΡŒΡΡ ошибкой OperationCanceledException
373 // Π·Π°Π²Π΅Ρ€ΡˆΠ°Ρ‚ΡŒΡΡ ошибкой OperationCanceledException
342 var p = PromiseHelper
374 var p = PromiseHelper
343 .Sleep(1, "Hi, HAL!")
375 .Sleep(1, "Hi, HAL!")
344 .Chain(x => {
376 .Then(x => {
345 // запускаСм Π΄Π²Π΅ асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ
377 // запускаСм Π΄Π²Π΅ асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ
346 var result = PromiseHelper.Sleep(1000, "HEM ENABLED!!!");
378 var result = PromiseHelper.Sleep(1000, "HEM ENABLED!!!");
347 // вторая опСрация отмСняСт ΠΏΠ΅Ρ€Π²ΡƒΡŽ Π΄ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ
379 // вторая опСрация отмСняСт ΠΏΠ΅Ρ€Π²ΡƒΡŽ Π΄ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ
348 PromiseHelper
380 PromiseHelper
349 .Sleep(100, "HAL, STOP!")
381 .Sleep(100, "HAL, STOP!")
350 .Then(() => result.Cancel());
382 .Then(() => result.Cancel());
351 return result;
383 return result;
352 });
384 });
353 try {
385 try {
354 p.Join();
386 p.Join();
355 } catch (TargetInvocationException err) {
387 } catch (TargetInvocationException err) {
356 Assert.IsTrue(err.InnerException is OperationCanceledException);
388 Assert.IsTrue(err.InnerException is OperationCanceledException);
357 }
389 }
358 }
390 }
359
391
360 [TestMethod]
392 [TestMethod]
361 public void ChainedCancel2Test() {
393 public void ChainedCancel2Test() {
362 // ΠΏΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ, Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Ρ‚Π°ΠΊΠΆΠ΅ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΎΡ‚ΠΌΠ΅Π½ΡΡ‚ΡŒΡΡ
394 // ΠΏΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ, Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Ρ‚Π°ΠΊΠΆΠ΅ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΎΡ‚ΠΌΠ΅Π½ΡΡ‚ΡŒΡΡ
363 IPromise p = null;
364 var pSurvive = new Promise<bool>();
395 var pSurvive = new Promise<bool>();
365 var hemStarted = new ManualResetEvent(false);
396 var hemStarted = new ManualResetEvent(false);
366 p = PromiseHelper
397 var p = PromiseHelper
367 .Sleep(1, "Hi, HAL!")
398 .Sleep(1, "Hi, HAL!")
368 .Chain(x => {
399 .Chain(x => {
369 hemStarted.Set();
400 hemStarted.Set();
370 // запускаСм Π΄Π²Π΅ асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ
401 // запускаСм Π΄Π²Π΅ асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ
371 var result = PromiseHelper
402 var result = PromiseHelper
372 .Sleep(1000, "HEM ENABLED!!!")
403 .Sleep(10000, "HEM ENABLED!!!")
373 .Then(s => pSurvive.Resolve(false));
404 .Then(s => pSurvive.Resolve(false));
374
405
375 result
406 result
376 .Cancelled(() => pSurvive.Resolve(true));
407 .Cancelled(() => pSurvive.Resolve(true));
377
408
378 return result;
409 return result;
379 });
410 });
380
411
381 hemStarted.WaitOne();
412 hemStarted.WaitOne();
382 p.Cancel();
413 p.Cancel();
383
414
384 try {
415 try {
385 p.Join();
416 p.Join();
386 } catch (OperationCanceledException) {
417 } catch (OperationCanceledException) {
387 Assert.IsTrue(pSurvive.Join());
418 Assert.IsTrue(pSurvive.Join());
388 }
419 }
389 }
420 }
390 }
421 }
391 }
422 }
392
423
@@ -1,238 +1,238
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
3 using System.Linq;
4 using System.Text;
4 using System.Text;
5 using System.Threading;
5 using System.Threading;
6 using System.Threading.Tasks;
6 using System.Threading.Tasks;
7
7
8 namespace Implab.Diagnostics {
8 namespace Implab.Diagnostics {
9 /// <summary>
9 /// <summary>
10 /// ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки, привязываСтся ΠΊ ΠΏΠΎΡ‚ΠΎΠΊΡƒ ΠΈ содСрТит Π² сСбС ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ стСкС логичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ.
10 /// ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки, привязываСтся ΠΊ ΠΏΠΎΡ‚ΠΎΠΊΡƒ ΠΈ содСрТит Π² сСбС ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ стСкС логичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ.
11 /// </summary>
11 /// </summary>
12 /// <remarks>
12 /// <remarks>
13 /// ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки пСрСдаСтся ΡΠ»ΡƒΡˆΠ°Ρ‚Π΅Π»ΡΠΌ событий для опрСдСлСния мСста, Π³Π΄Π΅ Π²ΠΎΠ·Π½ΠΈΠΊΠ»ΠΎ событиС.
13 /// ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки пСрСдаСтся ΡΠ»ΡƒΡˆΠ°Ρ‚Π΅Π»ΡΠΌ событий для опрСдСлСния мСста, Π³Π΄Π΅ Π²ΠΎΠ·Π½ΠΈΠΊΠ»ΠΎ событиС.
14 /// </remarks>
14 /// </remarks>
15 public class TraceContext {
15 public class TraceContext {
16 LogicalOperation m_currentOperation;
16 LogicalOperation m_currentOperation;
17 readonly LogicalOperation m_bound;
17 readonly LogicalOperation m_bound;
18 readonly int m_threadId;
18 readonly int m_threadId;
19
19
20 [ThreadStatic]
20 [ThreadStatic]
21 static TraceContext _current;
21 static TraceContext _current;
22
22
23 /// <summary>
23 /// <summary>
24 /// Π’Π΅ΠΊΡƒΡ‰ΠΈΠΉ контСкст трассировки для ΠΏΠΎΡ‚ΠΎΠΊΠ°, создаСтся астоматичСски ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΌ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ.
24 /// Π’Π΅ΠΊΡƒΡ‰ΠΈΠΉ контСкст трассировки для ΠΏΠΎΡ‚ΠΎΠΊΠ°, создаСтся астоматичСски ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΌ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ.
25 /// </summary>
25 /// </summary>
26 public static TraceContext Current {
26 public static TraceContext Current {
27 get {
27 get {
28 if (_current == null) {
28 if (_current == null) {
29 _current = new TraceContext();
29 _current = new TraceContext();
30 _current.LogEvent(TraceEventType.Created,"[{0}]", _current.ThreadId);
30 _current.LogEvent(TraceEventType.Created,"[{0}]", _current.ThreadId);
31 }
31 }
32 return _current;
32 return _current;
33 }
33 }
34 }
34 }
35
35
36 TraceContext(TraceContext context)
36 TraceContext(TraceContext context)
37 : this(context, false) {
37 : this(context, false) {
38 }
38 }
39
39
40 TraceContext(TraceContext context, bool attach) {
40 TraceContext(TraceContext context, bool attach) {
41 if (context == null)
41 if (context == null)
42 throw new ArgumentNullException("context");
42 throw new ArgumentNullException("context");
43
43
44 m_currentOperation = context.CurrentOperation;
44 m_currentOperation = context.CurrentOperation;
45 m_bound = attach ? context.BoundOperation : context.CurrentOperation;
45 m_bound = attach ? context.BoundOperation : context.CurrentOperation;
46 m_threadId = Thread.CurrentThread.ManagedThreadId;
46 m_threadId = Thread.CurrentThread.ManagedThreadId;
47 }
47 }
48
48
49 TraceContext() {
49 TraceContext() {
50 m_currentOperation = new LogicalOperation();
50 m_currentOperation = new LogicalOperation();
51 m_bound = m_currentOperation;
51 m_bound = m_currentOperation;
52 m_threadId = Thread.CurrentThread.ManagedThreadId;
52 m_threadId = Thread.CurrentThread.ManagedThreadId;
53 }
53 }
54
54
55 /// <summary>
55 /// <summary>
56 /// ΠŸΡ€ΠΈ нСобходимости ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅Ρ‚ состояниС контСкста трассивровки Π² Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ.
56 /// ΠŸΡ€ΠΈ нСобходимости ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅Ρ‚ состояниС контСкста трассивровки Π² Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ.
57 /// </summary>
57 /// </summary>
58 /// <param name="from">Π˜ΡΡ…ΠΎΠ΄Π½Ρ‹ΠΉ контСкст трассировки, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ пСрСдаСтся.</param>
58 /// <param name="from">Π˜ΡΡ…ΠΎΠ΄Π½Ρ‹ΠΉ контСкст трассировки, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ пСрСдаСтся.</param>
59 /// <remarks>
59 /// <remarks>
60 /// <para>
60 /// <para>
61 /// ΠšΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ происходит Π·Π° счСт создания Π½ΠΎΠ²ΠΎΠ³ΠΎ контСкста трассировки ΠΈ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ΠΌ Π΅Π³ΠΎ
61 /// ΠšΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ происходит Π·Π° счСт создания Π½ΠΎΠ²ΠΎΠ³ΠΎ контСкста трассировки ΠΈ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ΠΌ Π΅Π³ΠΎ
62 /// состояния ΠΈΠ· ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠ³ΠΎ контСкста. ΠŸΡ€ΠΈ этом копируСтся стСк ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ, ΠΎΠ΄Π½Π°ΠΊΠΎ Π² Π½ΠΎΠ²ΠΎΠΌ
62 /// состояния ΠΈΠ· ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠ³ΠΎ контСкста. ΠŸΡ€ΠΈ этом копируСтся стСк ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ, ΠΎΠ΄Π½Π°ΠΊΠΎ Π² Π½ΠΎΠ²ΠΎΠΌ
63 /// контСкстС Ρ€Π°Π½Π΅Π΅ Π½Π°Ρ‡Π°Ρ‚Ρ‹Π΅ логичСскиС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Ρ‹.
63 /// контСкстС Ρ€Π°Π½Π΅Π΅ Π½Π°Ρ‡Π°Ρ‚Ρ‹Π΅ логичСскиС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Ρ‹.
64 /// </para>
64 /// </para>
65 /// <para>
65 /// <para>
66 /// Если ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π° состояния ΡΠΎΡΡ‚ΠΎΡΠ»Π°ΡΡŒ, Ρ‚ΠΎ вызываСтся событиС трассировки <see cref="TraceEventType.Fork"/>.
66 /// Если ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π° состояния ΡΠΎΡΡ‚ΠΎΡΠ»Π°ΡΡŒ, Ρ‚ΠΎ вызываСтся событиС трассировки <see cref="TraceEventType.Fork"/>.
67 /// </para>
67 /// </para>
68 /// </remarks>
68 /// </remarks>
69 public static void Fork(TraceContext from) {
69 public static void Fork(TraceContext from) {
70 if (_current == from)
70 if (_current == from)
71 return;
71 return;
72 if (from != null) {
72 if (from != null) {
73 var context = new TraceContext(from);
73 var context = new TraceContext(from);
74 context.LogEvent(TraceEventType.Fork, "[{0}]-->[{1}]",from.ThreadId, context.ThreadId);
74 context.LogEvent(TraceEventType.Fork, "[{0}]-->[{1}]",from.ThreadId, context.ThreadId);
75 _current = context;
75 _current = context;
76 } else {
76 } else {
77 _current = new TraceContext();
77 _current = new TraceContext();
78 }
78 }
79 }
79 }
80
80
81 /// <summary>
81 /// <summary>
82 /// Π—Π°Π΄Π°Π΅Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌΡƒ ΠΏΠΎΡ‚ΠΎΠΊΡƒ ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΉ контСкст, Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ ΠΌΠΎΠΆΠ΅Ρ‚ Π·Π°ΠΊΠ°Π½Ρ‡ΠΈΠ²Π°Ρ‚ΡŒ Ρ€Π°Π½Π΅Π΅ Π½Π°Ρ‡Π°Ρ‚Ρ‹Π΅
82 /// Π—Π°Π΄Π°Π΅Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌΡƒ ΠΏΠΎΡ‚ΠΎΠΊΡƒ ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΉ контСкст, Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ ΠΌΠΎΠΆΠ΅Ρ‚ Π·Π°ΠΊΠ°Π½Ρ‡ΠΈΠ²Π°Ρ‚ΡŒ Ρ€Π°Π½Π΅Π΅ Π½Π°Ρ‡Π°Ρ‚Ρ‹Π΅
83 /// логичСскиС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π² ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΌ контСкстС.
83 /// логичСскиС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π² ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΌ контСкстС.
84 /// </summary>
84 /// </summary>
85 /// <param name="source"></param>
85 /// <param name="source"></param>
86 public static void Attach(TraceContext source) {
86 public static void Attach(TraceContext source) {
87 if (_current == source)
87 if (_current == source)
88 return;
88 return;
89 if (source != null) {
89 if (source != null) {
90 var context = new TraceContext(source, true);
90 var context = new TraceContext(source, true);
91 context.LogEvent(TraceEventType.Attach, "[{0}]-->[{1}]", source.ThreadId, context.ThreadId);
91 context.LogEvent(TraceEventType.Attach, "[{0}]-->[{1}]", source.ThreadId, context.ThreadId);
92 _current = context;
92 _current = context;
93 } else {
93 } else {
94 _current = new TraceContext();
94 _current = new TraceContext();
95 }
95 }
96 }
96 }
97
97
98 /// <summary>
98 /// <summary>
99 /// ΠžΡ‚ΡΠΎΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ контСкст трассировки ΠΎΡ‚ ΠΏΠΎΡ‚ΠΎΠΊΠ°, для дальнСйшСй Π΅Π³ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Π΄Ρ€ΡƒΠ³ΠΎΠΌΡƒ ΠΏΠΎΡ‚ΠΎΠΊΡƒ
99 /// ΠžΡ‚ΡΠΎΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ контСкст трассировки ΠΎΡ‚ ΠΏΠΎΡ‚ΠΎΠΊΠ°, для дальнСйшСй Π΅Π³ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Π΄Ρ€ΡƒΠ³ΠΎΠΌΡƒ ΠΏΠΎΡ‚ΠΎΠΊΡƒ
100 /// <see cref="Attach(TraceContext)"/>.
100 /// <see cref="Attach(TraceContext)"/>.
101 /// </summary>
101 /// </summary>
102 /// <returns>ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки ΠΏΠΎΡ‚ΠΎΠΊΠ°</returns>
102 /// <returns>ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки ΠΏΠΎΡ‚ΠΎΠΊΠ°</returns>
103 /// <remarks>
103 /// <remarks>
104 /// ПослС отсоСдинСния контСкста трассировки ΠΎΡ‚ ΠΏΠΎΡ‚ΠΎΠΊΠ°, ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΌ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ ΠΊ трассировкС Π² этом
104 /// ПослС отсоСдинСния контСкста трассировки ΠΎΡ‚ ΠΏΠΎΡ‚ΠΎΠΊΠ°, ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΌ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ ΠΊ трассировкС Π² этом
105 /// ΠΏΠΎΡ‚ΠΎΠΊΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ создан Π½ΠΎΠ²Ρ‹ΠΉ контСкст.
105 /// ΠΏΠΎΡ‚ΠΎΠΊΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ создан Π½ΠΎΠ²Ρ‹ΠΉ контСкст.
106 /// </remarks>
106 /// </remarks>
107 public static TraceContext Detach() {
107 public static TraceContext Detach() {
108 var context = Current;
108 var context = Current;
109 context.LogEvent(TraceEventType.Detach, null);
109 context.LogEvent(TraceEventType.Detach, null);
110 _current = null;
110 _current = null;
111 return context;
111 return context;
112 }
112 }
113
113
114 /// <summary>
114 /// <summary>
115 /// Π‘ΠΎΠ·Π΄Π°Π΅Ρ‚ ΠΏΠΎΡΡ‚ΠΎΡΠ½Π½ΡƒΡŽ копию Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ контСкста, Π΄Π°Π½Π½ΡƒΡŽ копию ΠΌΠΎΠΆΠ½ΠΎ Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒ ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ для ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Ρ‡Π΅Ρ€Π΅Π· <see cref="Fork(TraceContext)"/>
115 /// Π‘ΠΎΠ·Π΄Π°Π΅Ρ‚ ΠΏΠΎΡΡ‚ΠΎΡΠ½Π½ΡƒΡŽ копию Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ контСкста, Π΄Π°Π½Π½ΡƒΡŽ копию ΠΌΠΎΠΆΠ½ΠΎ Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒ ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ для ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Ρ‡Π΅Ρ€Π΅Π· <see cref="Fork(TraceContext)"/>
116 /// </summary>
116 /// </summary>
117 /// <returns>Копия Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ контСкста трассировки.</returns>
117 /// <returns>Копия Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ контСкста трассировки.</returns>
118 public static TraceContext Snapshot() {
118 public static TraceContext Snapshot() {
119 return _current == null ? new TraceContext() : new TraceContext(_current,false);
119 return _current == null ? new TraceContext() : new TraceContext(_current,false);
120 }
120 }
121
121
122 /// <summary>
122 /// <summary>
123 /// ВыполняСт ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠ΅ дСйствиС Π² ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΌ контСкстС трассировки, ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΠΈ восстанавливаСт ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠΉ контСкст трассировки ΠΏΠΎΡ‚ΠΎΠΊΠ°.
123 /// ВыполняСт ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠ΅ дСйствиС Π² ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΌ контСкстС трассировки, ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΠΈ восстанавливаСт ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠΉ контСкст трассировки ΠΏΠΎΡ‚ΠΎΠΊΠ°.
124 /// </summary>
124 /// </summary>
125 /// <param name="action"></param>
125 /// <param name="action"></param>
126 public void Invoke(Action action) {
126 public void Invoke(Action action) {
127 if (action == null)
127 if (action == null)
128 throw new ArgumentNullException("action");
128 throw new ArgumentNullException("action");
129 var old = _current;
129 var old = _current;
130 Fork(this);
130 Fork(this);
131 try {
131 try {
132 action();
132 action();
133 } finally {
133 } finally {
134 if(_current != null)
134 if(_current != null)
135 _current.EndAllOperations();
135 _current.EndAllOperations();
136 _current = old;
136 _current = old;
137 }
137 }
138 }
138 }
139
139
140 /// <summary>
140 /// <summary>
141 /// ВСкущая логичСская опСрация.
141 /// ВСкущая логичСская опСрация.
142 /// </summary>
142 /// </summary>
143 public LogicalOperation CurrentOperation {
143 public LogicalOperation CurrentOperation {
144 get {
144 get {
145 return m_currentOperation;
145 return m_currentOperation;
146 }
146 }
147 }
147 }
148
148
149 /// <summary>
149 /// <summary>
150 /// ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΡ Π½ΠΈΠΆΠ΅ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ нСльзя ΠΎΠΏΡƒΡΠΊΠ°Ρ‚ΡŒΡΡ Π² стСкС логичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ, Ρ‚.Π΅. ΠΎΠ½Π° Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Π° Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ контСкстС.
150 /// ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΡ Π½ΠΈΠΆΠ΅ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ нСльзя ΠΎΠΏΡƒΡΠΊΠ°Ρ‚ΡŒΡΡ Π² стСкС логичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ, Ρ‚.Π΅. ΠΎΠ½Π° Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Π° Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ контСкстС.
151 /// </summary>
151 /// </summary>
152 public LogicalOperation BoundOperation {
152 public LogicalOperation BoundOperation {
153 get {
153 get {
154 return m_bound;
154 return m_bound;
155 }
155 }
156 }
156 }
157
157
158 /// <summary>
158 /// <summary>
159 /// ΠŸΠΎΡ‚ΠΎΠΊ, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ создан контСкст трассировки.
159 /// ΠŸΠΎΡ‚ΠΎΠΊ, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ создан контСкст трассировки.
160 /// </summary>
160 /// </summary>
161 public int ThreadId {
161 public int ThreadId {
162 get {
162 get {
163 return m_threadId;
163 return m_threadId;
164 }
164 }
165 }
165 }
166
166
167 /// <summary>
167 /// <summary>
168 /// НачинаСт Π±Π΅Π·Ρ‹ΠΌΡΠ½Π½ΡƒΡŽ Π»ΠΎΠ³ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ.
168 /// НачинаСт Π±Π΅Π·Ρ‹ΠΌΡΠ½Π½ΡƒΡŽ Π»ΠΎΠ³ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ.
169 /// </summary>
169 /// </summary>
170 public void StartLogicalOperation() {
170 public void StartLogicalOperation() {
171 StartLogicalOperation(null);
171 StartLogicalOperation(null);
172 }
172 }
173
173
174 /// <summary>
174 /// <summary>
175 /// НачинаСт Π»ΠΎΠ³ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ с ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΌ ΠΈΠΌΠ΅Π½Π΅ΠΌ. Бозданная опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π΄ΠΎΠ±Π²Π°Π»Π΅Π½Π° Π² стСк логичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ контСкста, Π·Π°Ρ‚Π΅ΠΌ Π±ΡƒΠ΄Π΅Ρ‚ создано ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΠ²ΡƒΡŽΡ‰Π΅Π΅ событиС.
175 /// НачинаСт Π»ΠΎΠ³ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ с ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΌ ΠΈΠΌΠ΅Π½Π΅ΠΌ. Бозданная опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π΄ΠΎΠ±Π²Π°Π»Π΅Π½Π° Π² стСк логичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ контСкста, Π·Π°Ρ‚Π΅ΠΌ Π±ΡƒΠ΄Π΅Ρ‚ создано ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΠ²ΡƒΡŽΡ‰Π΅Π΅ событиС.
176 /// </summary>
176 /// </summary>
177 /// <param name="name">Имя Π½Π°Ρ‡ΠΈΠ½Π°Π΅ΠΌΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
177 /// <param name="name">Имя Π½Π°Ρ‡ΠΈΠ½Π°Π΅ΠΌΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
178 public void StartLogicalOperation(string name) {
178 public void StartLogicalOperation(string name) {
179 m_currentOperation = new LogicalOperation(name, m_currentOperation);
179 m_currentOperation = new LogicalOperation(name, m_currentOperation);
180 LogEvent(TraceEventType.OperationStarted, name);
180 LogEvent(TraceEventType.OperationStarted, name);
181 }
181 }
182
182
183 /// <summary>
183 /// <summary>
184 /// Π—Π°ΠΊΠ°Π½Ρ‡ΠΈΠ²Π°Π΅Ρ‚ Π»ΠΎΠ³ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ Π½Π°Ρ‡Π°Ρ‚ΡƒΡŽ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ контСкстС. ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, Π½Π°Ρ‡Π°Ρ‚Ρ‹Π΅ Π² Π΄Ρ€ΡƒΠ³ΠΈΡ… контСкстах Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π·Π°ΠΊΠΎΠ½Ρ‡Π΅Π½Ρ‹ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ контСкстС.
184 /// Π—Π°ΠΊΠ°Π½Ρ‡ΠΈΠ²Π°Π΅Ρ‚ Π»ΠΎΠ³ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ Π½Π°Ρ‡Π°Ρ‚ΡƒΡŽ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ контСкстС. ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, Π½Π°Ρ‡Π°Ρ‚Ρ‹Π΅ Π² Π΄Ρ€ΡƒΠ³ΠΈΡ… контСкстах Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π·Π°ΠΊΠΎΠ½Ρ‡Π΅Π½Ρ‹ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ контСкстС.
185 /// </summary>
185 /// </summary>
186 /// <remarks>
186 /// <remarks>
187 /// ΠŸΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° создаСтся событиС ΠΆΡƒΡ€Π½Π°Π»Π° трассировки, Π»ΠΈΠ±ΠΎ ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, Π»ΠΈΠ±ΠΎ ΠΎΠ± ошибки, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ данная опСрация
187 /// ΠŸΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° создаСтся событиС ΠΆΡƒΡ€Π½Π°Π»Π° трассировки, Π»ΠΈΠ±ΠΎ ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, Π»ΠΈΠ±ΠΎ ΠΎΠ± ошибки, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ данная опСрация
188 /// Π½Π°Ρ‡Π°Ρ‚Π° Π² Π΄Ρ€ΡƒΠ³ΠΎΠΌ контСкстС.
188 /// Π½Π°Ρ‡Π°Ρ‚Π° Π² Π΄Ρ€ΡƒΠ³ΠΎΠΌ контСкстС.
189 /// </remarks>
189 /// </remarks>
190 public void EndLogicalOperation() {
190 public void EndLogicalOperation() {
191 if (m_bound == m_currentOperation) {
191 if (m_bound == m_currentOperation) {
192 LogEvent(TraceEventType.Error, "Trying to end the operation which isn't belongs to current trace");
192 LogEvent(TraceEventType.Error, "Trying to end the operation which isn't belongs to current trace");
193 } else {
193 } else {
194 var op = m_currentOperation;
194 var op = m_currentOperation;
195 LogEvent(TraceEventType.OperationCompleted, "{0} {1} ms", op.Name, op.Duration);
195 LogEvent(TraceEventType.OperationCompleted, "{0} {1} ms", op.Name, op.Duration);
196 m_currentOperation = m_currentOperation.Parent;
196 m_currentOperation = m_currentOperation.Parent;
197 }
197 }
198 }
198 }
199
199
200 /// <summary>
200 /// <summary>
201 /// Π‘ΠΎΠ·Π΄Π°Π΅Ρ‚ копию контСкста ΠΈ возвращаСтся Π½Π° ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ контСкстС, это позволяСт Π½Π°Ρ‡Π°Ρ‚ΡŒ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΏΠΎΡ‚ΠΎΠΊΠ΅, Π° Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡŒ - Π² Π΄Ρ€ΡƒΠ³ΠΎΠΌ.
201 /// Π‘ΠΎΠ·Π΄Π°Π΅Ρ‚ копию контСкста ΠΈ возвращаСтся Π½Π° ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ контСкстС, это позволяСт Π½Π°Ρ‡Π°Ρ‚ΡŒ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΏΠΎΡ‚ΠΎΠΊΠ΅, Π° Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡŒ - Π² Π΄Ρ€ΡƒΠ³ΠΎΠΌ.
202 /// </summary>
202 /// </summary>
203 /// <returns>ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΈΡΠΎΠ΅Π΄ΠΈΠ½ΠΈΡ‚ΡŒ ΠΊ Π΄Ρ€ΡƒΠ³ΠΎΠΌΡƒ ΠΏΠΎΡ‚ΠΎΠΊΡƒ.</returns>
203 /// <returns>ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΈΡΠΎΠ΅Π΄ΠΈΠ½ΠΈΡ‚ΡŒ ΠΊ Π΄Ρ€ΡƒΠ³ΠΎΠΌΡƒ ΠΏΠΎΡ‚ΠΎΠΊΡƒ.</returns>
204 public TraceContext DetachLogicalOperation() {
204 public TraceContext DetachLogicalOperation() {
205 if (m_bound == m_currentOperation) {
205 if (m_bound == m_currentOperation) {
206 return new TraceContext();
206 return new TraceContext();
207 } else {
207 } else {
208 var detached = new TraceContext(this, true);
208 var detached = new TraceContext(this, true);
209 m_currentOperation = m_currentOperation.Parent;
209 m_currentOperation = m_currentOperation.Parent;
210 return detached;
210 return detached;
211 }
211 }
212 }
212 }
213
213
214 public void BindLogicalOperationToPromise(IPromise promise) {
214 public void BindLogicalOperationToPromise(IPromise promise) {
215 Safe.ArgumentNotNull(promise, "promise");
215 Safe.ArgumentNotNull(promise, "promise");
216
216
217 var ctx = DetachLogicalOperation();
217 var ctx = DetachLogicalOperation();
218 promise.Finally(() => {
218 promise.Anyway(() => {
219 var old = _current;
219 var old = _current;
220 TraceContext.Attach(ctx);
220 TraceContext.Attach(ctx);
221 TraceContext.Current.EndLogicalOperation();
221 TraceContext.Current.EndLogicalOperation();
222 _current = old;
222 _current = old;
223 });
223 });
224 }
224 }
225
225
226 /// <summary>
226 /// <summary>
227 /// Π—Π°Π²Ρ€Π΅ΡˆΠ°Π΅Ρ‚ всС Π½Π°Ρ‡Π°Ρ‚Ρ‹Π΅ Π² этом контСкстС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ
227 /// Π—Π°Π²Ρ€Π΅ΡˆΠ°Π΅Ρ‚ всС Π½Π°Ρ‡Π°Ρ‚Ρ‹Π΅ Π² этом контСкстС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ
228 /// </summary>
228 /// </summary>
229 public void EndAllOperations() {
229 public void EndAllOperations() {
230 while (m_bound != m_currentOperation)
230 while (m_bound != m_currentOperation)
231 EndLogicalOperation();
231 EndLogicalOperation();
232 }
232 }
233
233
234 void LogEvent(TraceEventType type, string format, params object[] args) {
234 void LogEvent(TraceEventType type, string format, params object[] args) {
235 LogChannel<TraceEvent>.Default.LogEvent(this, TraceEvent.Create(type, format, args));
235 LogChannel<TraceEvent>.Default.LogEvent(this, TraceEvent.Create(type, format, args));
236 }
236 }
237 }
237 }
238 }
238 }
@@ -1,10 +1,10
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
3 using System.Linq;
4 using System.Text;
4 using System.Text;
5
5
6 namespace Implab {
6 namespace Implab {
7 public interface ICancellable {
7 public interface ICancellable {
8 bool Cancel();
8 void Cancel();
9 }
9 }
10 }
10 }
@@ -1,82 +1,82
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
3 using System.Linq;
4 using System.Text;
4 using System.Text;
5
5
6 namespace Implab {
6 namespace Implab {
7 public interface IPromise: ICancellable {
7 public interface IPromise: ICancellable {
8 /// <summary>
8 /// <summary>
9 /// Check whereather the promise has no more than one dependent promise.
9 /// Check whereather the promise has no more than one dependent promise.
10 /// </summary>
10 /// </summary>
11 bool IsExclusive {
11 bool IsExclusive {
12 get;
12 get;
13 }
13 }
14
14
15 /// <summary>
15 /// <summary>
16 /// Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌΠΎΠ³ΠΎ Ρ‡Π΅Ρ€Π΅Π· Π΄Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅.
16 /// Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌΠΎΠ³ΠΎ Ρ‡Π΅Ρ€Π΅Π· Π΄Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅.
17 /// </summary>
17 /// </summary>
18 Type PromiseType { get; }
18 Type PromiseType { get; }
19
19
20 /// <summary>
20 /// <summary>
21 /// ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ являСтся Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Ρ‹ΠΌ, Π»ΠΈΠ±ΠΎ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ, Π»ΠΈΠ±ΠΎ с ошибкой.
21 /// ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ являСтся Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Ρ‹ΠΌ, Π»ΠΈΠ±ΠΎ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ, Π»ΠΈΠ±ΠΎ с ошибкой.
22 /// </summary>
22 /// </summary>
23 bool IsResolved { get; }
23 bool IsResolved { get; }
24
24
25 /// <summary>
25 /// <summary>
26 /// ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±Ρ‹Π»ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½ΠΎ.
26 /// ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±Ρ‹Π»ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½ΠΎ.
27 /// </summary>
27 /// </summary>
28 bool IsCancelled { get; }
28 bool IsCancelled { get; }
29
29
30 IPromise Then(Action success, ErrorHandler error, Action cancel);
30 IPromise Then(Action success, ErrorHandler error, Action cancel);
31 IPromise Then(Action success, ErrorHandler error);
31 IPromise Then(Action success, ErrorHandler error);
32 IPromise Then(Action success);
32 IPromise Then(Action success);
33
33
34 /// <summary>
34 /// <summary>
35 /// ДобавляСт послСднй ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ, Π½Π΅ создаСт ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
35 /// ДобавляСт послСднй ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ, Π½Π΅ создаСт ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
36 /// </summary>
36 /// </summary>
37 /// <param name="success">Success.</param>
37 /// <param name="success">Success.</param>
38 /// <param name="error">Error.</param>
38 /// <param name="error">Error.</param>
39 /// <param name="cancel">Cancel.</param>
39 /// <param name="cancel">Cancel.</param>
40 void Last(Action success, ErrorHandler error, Action cancel);
40 void Last(Action success, ErrorHandler error, Action cancel);
41 void Last(Action success, ErrorHandler error);
41 void Last(Action success, ErrorHandler error);
42 void Last(Action success);
42 void Last(Action success);
43
43
44 IPromise Error(ErrorHandler error);
44 IPromise Error(ErrorHandler error);
45 /// <summary>
45 /// <summary>
46 /// ΠžΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ Π»ΠΈΠ±ΠΎ ΠΎΡˆΠΈΠ±ΠΊΡƒ, Π»ΠΈΠ±ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚. Π‘ΠΎΠ±Ρ‹Ρ‚ΠΈΠ΅ ΠΎΡ‚ΠΌΠ΅Π½Ρ‹ Π½Π΅ обрабатываСтся.
46 /// ΠžΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ Π»ΠΈΠ±ΠΎ ΠΎΡˆΠΈΠ±ΠΊΡƒ, Π»ΠΈΠ±ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚. Π‘ΠΎΠ±Ρ‹Ρ‚ΠΈΠ΅ ΠΎΡ‚ΠΌΠ΅Π½Ρ‹ Π½Π΅ обрабатываСтся.
47 /// </summary>
47 /// </summary>
48 /// <param name="handler">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ.</param>
48 /// <param name="handler">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ.</param>
49 /// <remarks>ПослС ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ ошибки, ΠΎΠ½Π° пСрСдаСтся дальшС.</remarks>
49 /// <remarks>ПослС ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ ошибки, ΠΎΠ½Π° пСрСдаСтся дальшС.</remarks>
50 /// <summary>
50 /// <summary>
51 /// ΠžΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ Π»ΠΈΠ±ΠΎ ΠΎΡˆΠΈΠ±ΠΊΡƒ, Π»ΠΈΠ±ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Π»ΠΈΠ±ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Ρƒ обСщания.
51 /// ΠžΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ Π»ΠΈΠ±ΠΎ ΠΎΡˆΠΈΠ±ΠΊΡƒ, Π»ΠΈΠ±ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Π»ΠΈΠ±ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Ρƒ обСщания.
52 /// </summary>
52 /// </summary>
53 /// <param name="handler">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ.</param>
53 /// <param name="handler">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ.</param>
54 /// <remarks>ПослС ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ ошибки, ΠΎΠ½Π° пСрСдаСтся дальшС.</remarks>
54 /// <remarks>ПослС ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ ошибки, ΠΎΠ½Π° пСрСдаСтся дальшС.</remarks>
55 IPromise Finally(Action handler);
55 IPromise Anyway(Action handler);
56 /// <summary>
56 /// <summary>
57 /// ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ для рСгистрации ΠΎΡ‚ΠΌΠ΅Π½Ρ‹ обСщания, событиС ΠΎΡ‚ΠΌΠ΅Π½Ρ‹ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΏΠΎΠ΄Π°Π²Π»Π΅Π½ΠΎ.
57 /// ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ для рСгистрации ΠΎΡ‚ΠΌΠ΅Π½Ρ‹ обСщания, событиС ΠΎΡ‚ΠΌΠ΅Π½Ρ‹ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΏΠΎΠ΄Π°Π²Π»Π΅Π½ΠΎ.
58 /// </summary>
58 /// </summary>
59 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, связанноС с Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΌ.</returns>
59 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, связанноС с Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΌ.</returns>
60 /// <param name="handler">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ события.</param>
60 /// <param name="handler">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ события.</param>
61 /// <remarks>Если ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, Ρ‚ΠΎ ΠΎΠ½ΠΎ пСрСдаСтся ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΡƒ ошибки, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ€Π°Π±ΠΎΡ‚Ρ‹
61 /// <remarks>Если ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, Ρ‚ΠΎ ΠΎΠ½ΠΎ пСрСдаСтся ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΡƒ ошибки, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ€Π°Π±ΠΎΡ‚Ρ‹
62 /// ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½ связанному ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΡŽ</remarks>
62 /// ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½ связанному ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΡŽ</remarks>
63 IPromise Cancelled(Action handler);
63 IPromise Cancelled(Action handler);
64
64
65 /// <summary>
65 /// <summary>
66 /// ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ обСщания ΠΊ Π·Π°Π΄Π°Π½Π½ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅.
66 /// ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ обСщания ΠΊ Π·Π°Π΄Π°Π½Π½ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅.
67 /// </summary>
67 /// </summary>
68 IPromise<T> Cast<T>();
68 IPromise<T> Cast<T>();
69
69
70 /// <summary>
70 /// <summary>
71 /// Π‘ΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ с ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ΠΌ.
71 /// Π‘ΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ с ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ΠΌ.
72 /// </summary>
72 /// </summary>
73 void Join();
73 void Join();
74 /// <summary>
74 /// <summary>
75 /// Π‘ΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ с ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ΠΌ.
75 /// Π‘ΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ с ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ΠΌ.
76 /// </summary>
76 /// </summary>
77 /// <param name="timeout">ВрСмя оТидания, ΠΏΠΎ Π΅Π³ΠΎ ΠΈΡΡ‚Π΅Ρ‡Π΅Π½ΠΈΡŽ Π²ΠΎΠ·Π½ΠΈΠΊΠ½Π΅Ρ‚ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.</param>
77 /// <param name="timeout">ВрСмя оТидания, ΠΏΠΎ Π΅Π³ΠΎ ΠΈΡΡ‚Π΅Ρ‡Π΅Π½ΠΈΡŽ Π²ΠΎΠ·Π½ΠΈΠΊΠ½Π΅Ρ‚ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.</param>
78 /// <exception cref="TimeoutException">ΠŸΡ€Π΅Π²Ρ‹ΡˆΠ΅Π½ΠΎ врСмя оТидания.</exception>
78 /// <exception cref="TimeoutException">ΠŸΡ€Π΅Π²Ρ‹ΡˆΠ΅Π½ΠΎ врСмя оТидания.</exception>
79 void Join(int timeout);
79 void Join(int timeout);
80
80
81 }
81 }
82 }
82 }
@@ -1,37 +1,43
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
3 using System.Linq;
4 using System.Text;
4 using System.Text;
5
5
6 namespace Implab {
6 namespace Implab {
7 public interface IPromise<T>: IPromise {
7 public interface IPromise<T> : IPromise {
8
8
9 new T Join();
9 new T Join();
10
10
11 new T Join(int timeout);
11 new T Join(int timeout);
12
12
13 void Last(ResultHandler<T> success, ErrorHandler error, Action cancel);
14
15 void Last(ResultHandler<T> success, ErrorHandler error);
16
17 void Last(ResultHandler<T> success);
18
13 IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error, Action cancel);
19 IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error, Action cancel);
14
20
15 IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error);
21 IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error);
16
22
17 IPromise<T> Then(ResultHandler<T> success);
23 IPromise<T> Then(ResultHandler<T> success);
18
24
19 void Last(ResultHandler<T> success, ErrorHandler error, Action cancel);
25 IPromise<T2> Then<T2>(ResultMapper<T, T2> mapper, ErrorHandler<T2> error, Action cancel);
20 void Last(ResultHandler<T> success, ErrorHandler error);
21 void Last(ResultHandler<T> success);
22
26
23 IPromise<T> Error(ErrorHandler<T> error);
27 IPromise<T2> Then<T2>(ResultMapper<T, T2> mapper, ErrorHandler<T2> error);
24
25 IPromise<T2> Then<T2>(ResultMapper<T,T2> mapper, ErrorHandler<T> error);
26
28
27 IPromise<T2> Then<T2>(ResultMapper<T,T2> mapper);
29 IPromise<T2> Then<T2>(ResultMapper<T, T2> mapper);
28
30
29 IPromise<T2> Then<T2>(ChainedOperation<T, T2> chained, ErrorHandler<T> error);
31 IPromise<T2> Chain<T2>(ResultMapper<T, IPromise<T2>> chained, ErrorHandler<IPromise<T2>> error, Action cancel);
32
33 IPromise<T2> Chain<T2>(ResultMapper<T, IPromise<T2>> chained, ErrorHandler<IPromise<T2>> error);
30
34
31 IPromise<T2> Then<T2>(ChainedOperation<T, T2> chained);
35 IPromise<T2> Chain<T2>(ResultMapper<T, IPromise<T2>> chained);
36
37 IPromise<T> Error(ErrorHandler<T> error);
32
38
33 new IPromise<T> Cancelled(Action handler);
39 new IPromise<T> Cancelled(Action handler);
34
40
35 new IPromise<T> Finally(Action handler);
41 new IPromise<T> Anyway(Action handler);
36 }
42 }
37 }
43 }
@@ -1,193 +1,193
1 using Implab.Diagnostics;
1 using Implab.Diagnostics;
2 using System;
2 using System;
3 using System.Collections.Generic;
3 using System.Collections.Generic;
4 using System.Diagnostics;
4 using System.Diagnostics;
5 using System.Linq;
5 using System.Linq;
6 using System.Text;
6 using System.Text;
7 using System.Threading;
7 using System.Threading;
8
8
9 namespace Implab.Parallels {
9 namespace Implab.Parallels {
10 public static class ArrayTraits {
10 public static class ArrayTraits {
11 class ArrayIterator<TSrc> : DispatchPool<int> {
11 class ArrayIterator<TSrc> : DispatchPool<int> {
12 readonly Action<TSrc> m_action;
12 readonly Action<TSrc> m_action;
13 readonly TSrc[] m_source;
13 readonly TSrc[] m_source;
14 readonly Promise<int> m_promise = new Promise<int>();
14 readonly Promise<int> m_promise = new Promise<int>();
15 readonly TraceContext m_traceContext;
15 readonly TraceContext m_traceContext;
16
16
17 int m_pending;
17 int m_pending;
18 int m_next;
18 int m_next;
19
19
20 public ArrayIterator(TSrc[] source, Action<TSrc> action, int threads)
20 public ArrayIterator(TSrc[] source, Action<TSrc> action, int threads)
21 : base(threads) {
21 : base(threads) {
22
22
23 Debug.Assert(source != null);
23 Debug.Assert(source != null);
24 Debug.Assert(action != null);
24 Debug.Assert(action != null);
25
25
26 m_traceContext = TraceContext.Snapshot();
26 m_traceContext = TraceContext.Snapshot();
27 m_next = 0;
27 m_next = 0;
28 m_source = source;
28 m_source = source;
29 m_pending = source.Length;
29 m_pending = source.Length;
30 m_action = action;
30 m_action = action;
31
31
32 m_promise.Finally(Dispose);
32 m_promise.Anyway(Dispose);
33
33
34 InitPool();
34 InitPool();
35 }
35 }
36
36
37 public Promise<int> Promise {
37 public Promise<int> Promise {
38 get {
38 get {
39 return m_promise;
39 return m_promise;
40 }
40 }
41 }
41 }
42
42
43 protected override void Worker() {
43 protected override void Worker() {
44 TraceContext.Fork(m_traceContext);
44 TraceContext.Fork(m_traceContext);
45 base.Worker();
45 base.Worker();
46 }
46 }
47
47
48 protected override bool TryDequeue(out int unit) {
48 protected override bool TryDequeue(out int unit) {
49 unit = Interlocked.Increment(ref m_next) - 1;
49 unit = Interlocked.Increment(ref m_next) - 1;
50 return unit < m_source.Length;
50 return unit < m_source.Length;
51 }
51 }
52
52
53 protected override void InvokeUnit(int unit) {
53 protected override void InvokeUnit(int unit) {
54 try {
54 try {
55 m_action(m_source[unit]);
55 m_action(m_source[unit]);
56 var pending = Interlocked.Decrement(ref m_pending);
56 var pending = Interlocked.Decrement(ref m_pending);
57 if (pending == 0)
57 if (pending == 0)
58 m_promise.Resolve(m_source.Length);
58 m_promise.Resolve(m_source.Length);
59 } catch (Exception e) {
59 } catch (Exception e) {
60 m_promise.Reject(e);
60 m_promise.Reject(e);
61 }
61 }
62 }
62 }
63 }
63 }
64
64
65 class ArrayMapper<TSrc, TDst>: DispatchPool<int> {
65 class ArrayMapper<TSrc, TDst>: DispatchPool<int> {
66 readonly Func<TSrc, TDst> m_transform;
66 readonly Func<TSrc, TDst> m_transform;
67 readonly TSrc[] m_source;
67 readonly TSrc[] m_source;
68 readonly TDst[] m_dest;
68 readonly TDst[] m_dest;
69 readonly Promise<TDst[]> m_promise = new Promise<TDst[]>();
69 readonly Promise<TDst[]> m_promise = new Promise<TDst[]>();
70 readonly TraceContext m_traceContext;
70 readonly TraceContext m_traceContext;
71
71
72 int m_pending;
72 int m_pending;
73 int m_next;
73 int m_next;
74
74
75 public ArrayMapper(TSrc[] source, Func<TSrc, TDst> transform, int threads)
75 public ArrayMapper(TSrc[] source, Func<TSrc, TDst> transform, int threads)
76 : base(threads) {
76 : base(threads) {
77
77
78 Debug.Assert (source != null);
78 Debug.Assert (source != null);
79 Debug.Assert( transform != null);
79 Debug.Assert( transform != null);
80
80
81 m_next = 0;
81 m_next = 0;
82 m_source = source;
82 m_source = source;
83 m_dest = new TDst[source.Length];
83 m_dest = new TDst[source.Length];
84 m_pending = source.Length;
84 m_pending = source.Length;
85 m_transform = transform;
85 m_transform = transform;
86 m_traceContext = TraceContext.Snapshot();
86 m_traceContext = TraceContext.Snapshot();
87
87
88 m_promise.Finally(Dispose);
88 m_promise.Anyway(Dispose);
89
89
90 InitPool();
90 InitPool();
91 }
91 }
92
92
93 public Promise<TDst[]> Promise {
93 public Promise<TDst[]> Promise {
94 get {
94 get {
95 return m_promise;
95 return m_promise;
96 }
96 }
97 }
97 }
98
98
99 protected override void Worker() {
99 protected override void Worker() {
100 TraceContext.Fork(m_traceContext);
100 TraceContext.Fork(m_traceContext);
101 base.Worker();
101 base.Worker();
102 }
102 }
103
103
104 protected override bool TryDequeue(out int unit) {
104 protected override bool TryDequeue(out int unit) {
105 unit = Interlocked.Increment(ref m_next) - 1;
105 unit = Interlocked.Increment(ref m_next) - 1;
106 return unit >= m_source.Length ? false : true;
106 return unit >= m_source.Length ? false : true;
107 }
107 }
108
108
109 protected override void InvokeUnit(int unit) {
109 protected override void InvokeUnit(int unit) {
110 try {
110 try {
111 m_dest[unit] = m_transform(m_source[unit]);
111 m_dest[unit] = m_transform(m_source[unit]);
112 var pending = Interlocked.Decrement(ref m_pending);
112 var pending = Interlocked.Decrement(ref m_pending);
113 if (pending == 0)
113 if (pending == 0)
114 m_promise.Resolve(m_dest);
114 m_promise.Resolve(m_dest);
115 } catch (Exception e) {
115 } catch (Exception e) {
116 m_promise.Reject(e);
116 m_promise.Reject(e);
117 }
117 }
118 }
118 }
119 }
119 }
120
120
121 public static IPromise<TDst[]> ParallelMap<TSrc, TDst> (this TSrc[] source, Func<TSrc,TDst> transform, int threads) {
121 public static IPromise<TDst[]> ParallelMap<TSrc, TDst> (this TSrc[] source, Func<TSrc,TDst> transform, int threads) {
122 if (source == null)
122 if (source == null)
123 throw new ArgumentNullException("source");
123 throw new ArgumentNullException("source");
124 if (transform == null)
124 if (transform == null)
125 throw new ArgumentNullException("transform");
125 throw new ArgumentNullException("transform");
126
126
127 var mapper = new ArrayMapper<TSrc, TDst>(source, transform, threads);
127 var mapper = new ArrayMapper<TSrc, TDst>(source, transform, threads);
128 return mapper.Promise;
128 return mapper.Promise;
129 }
129 }
130
130
131 public static IPromise<int> ParallelForEach<TSrc>(this TSrc[] source, Action<TSrc> action, int threads) {
131 public static IPromise<int> ParallelForEach<TSrc>(this TSrc[] source, Action<TSrc> action, int threads) {
132 if (source == null)
132 if (source == null)
133 throw new ArgumentNullException("source");
133 throw new ArgumentNullException("source");
134 if (action == null)
134 if (action == null)
135 throw new ArgumentNullException("action");
135 throw new ArgumentNullException("action");
136
136
137 var iter = new ArrayIterator<TSrc>(source, action, threads);
137 var iter = new ArrayIterator<TSrc>(source, action, threads);
138 return iter.Promise;
138 return iter.Promise;
139 }
139 }
140
140
141 public static IPromise<TDst[]> ChainedMap<TSrc, TDst>(this TSrc[] source, ChainedOperation<TSrc, TDst> transform, int threads) {
141 public static IPromise<TDst[]> ChainedMap<TSrc, TDst>(this TSrc[] source, ResultMapper<TSrc, IPromise<TDst>> transform, int threads) {
142 if (source == null)
142 if (source == null)
143 throw new ArgumentNullException("source");
143 throw new ArgumentNullException("source");
144 if (transform == null)
144 if (transform == null)
145 throw new ArgumentNullException("transform");
145 throw new ArgumentNullException("transform");
146 if (threads <= 0)
146 if (threads <= 0)
147 throw new ArgumentOutOfRangeException("Threads number must be greater then zero");
147 throw new ArgumentOutOfRangeException("Threads number must be greater then zero");
148
148
149 if (source.Length == 0)
149 if (source.Length == 0)
150 return Promise<TDst[]>.ResultToPromise(new TDst[0]);
150 return Promise<TDst[]>.ResultToPromise(new TDst[0]);
151
151
152 var promise = new Promise<TDst[]>();
152 var promise = new Promise<TDst[]>();
153 var res = new TDst[source.Length];
153 var res = new TDst[source.Length];
154 var pending = source.Length;
154 var pending = source.Length;
155
155
156 var semaphore = new Semaphore(threads, threads);
156 var semaphore = new Semaphore(threads, threads);
157
157
158 // Analysis disable AccessToDisposedClosure
158 // Analysis disable AccessToDisposedClosure
159 AsyncPool.InvokeNewThread(() => {
159 AsyncPool.InvokeNewThread(() => {
160 for (int i = 0; i < source.Length; i++) {
160 for (int i = 0; i < source.Length; i++) {
161 if(promise.IsResolved)
161 if(promise.IsResolved)
162 break; // stop processing in case of error or cancellation
162 break; // stop processing in case of error or cancellation
163 var idx = i;
163 var idx = i;
164
164
165 semaphore.WaitOne();
165 semaphore.WaitOne();
166 try {
166 try {
167 var p1 = transform(source[i]);
167 var p1 = transform(source[i]);
168 p1.Finally(() => semaphore.Release());
168 p1.Anyway(() => semaphore.Release());
169 p1.Then(
169 p1.Then(
170 x => {
170 x => {
171 res[idx] = x;
171 res[idx] = x;
172 var left = Interlocked.Decrement(ref pending);
172 var left = Interlocked.Decrement(ref pending);
173 if (left == 0)
173 if (left == 0)
174 promise.Resolve(res);
174 promise.Resolve(res);
175 },
175 },
176 e => {
176 e => {
177 promise.Reject(e);
177 promise.Reject(e);
178 throw new TransientPromiseException(e);
178 throw new TransientPromiseException(e);
179 }
179 }
180 );
180 );
181
181
182 } catch (Exception e) {
182 } catch (Exception e) {
183 promise.Reject(e);
183 promise.Reject(e);
184 }
184 }
185 }
185 }
186 return 0;
186 return 0;
187 });
187 });
188
188
189 return promise.Finally(semaphore.Dispose);
189 return promise.Anyway(semaphore.Dispose);
190 }
190 }
191
191
192 }
192 }
193 }
193 }
@@ -1,764 +1,820
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Reflection;
3 using System.Reflection;
4 using System.Diagnostics;
4 using System.Diagnostics;
5 using System.Threading;
5 using System.Threading;
6 using Implab.Parallels;
6 using Implab.Parallels;
7
7
8 namespace Implab {
8 namespace Implab {
9
9
10 public delegate void ErrorHandler(Exception e);
10 public delegate void ErrorHandler(Exception e);
11 public delegate T ErrorHandler<out T>(Exception e);
11 public delegate T ErrorHandler<out T>(Exception e);
12 public delegate void ResultHandler<in T>(T result);
12 public delegate void ResultHandler<in T>(T result);
13 public delegate TNew ResultMapper<in TSrc,out TNew>(TSrc result);
13 public delegate TNew ResultMapper<in TSrc,out TNew>(TSrc result);
14 public delegate IPromise<TNew> ChainedOperation<in TSrc,TNew>(TSrc result);
15
14
16 /// <summary>
15 /// <summary>
17 /// Класс для асинхронного получСния Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ². Π’Π°ΠΊ Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΠΎΠ΅ "ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅".
16 /// Класс для асинхронного получСния Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ². Π’Π°ΠΊ Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΠΎΠ΅ "ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅".
18 /// </summary>
17 /// </summary>
19 /// <typeparam name="T">Π’ΠΈΠΏ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌΠΎΠ³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°</typeparam>
18 /// <typeparam name="T">Π’ΠΈΠΏ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌΠΎΠ³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°</typeparam>
20 /// <remarks>
19 /// <remarks>
21 /// <para>БСрвис ΠΏΡ€ΠΈ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ ΠΊ Π΅Π³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρƒ Π΄Π°Π΅Ρ‚ ΠΎΠ±Π΅Ρ‰Π°ΠΈΠ½ΠΈΠ΅ ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ,
20 /// <para>БСрвис ΠΏΡ€ΠΈ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ ΠΊ Π΅Π³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρƒ Π΄Π°Π΅Ρ‚ ΠΎΠ±Π΅Ρ‰Π°ΠΈΠ½ΠΈΠ΅ ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ,
22 /// ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ² Ρ‚Π°ΠΊΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ряд ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹Ρ… Π²Ρ‹Π·ΠΎΠ²ΠΎ для получСния
21 /// ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ² Ρ‚Π°ΠΊΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ряд ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹Ρ… Π²Ρ‹Π·ΠΎΠ²ΠΎ для получСния
23 /// событий выполнСния обСщания, Ρ‚ΠΎΠ΅ΡΡ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΈ прСдоставлСнии Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ².</para>
22 /// событий выполнСния обСщания, Ρ‚ΠΎΠ΅ΡΡ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΈ прСдоставлСнии Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ².</para>
24 /// <para>
23 /// <para>
25 /// ΠžΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚Π°ΠΊ ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ с ошибкой. Для подписки Π½Π°
24 /// ΠžΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚Π°ΠΊ ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ с ошибкой. Для подписки Π½Π°
26 /// Π΄Π°Π½Π½Ρ‹Π΅ события ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Then</c>.
25 /// Π΄Π°Π½Π½Ρ‹Π΅ события ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Then</c>.
27 /// </para>
26 /// </para>
28 /// <para>
27 /// <para>
29 /// БСрвис, Π² свою ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ, ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ (Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ с ошибкой),
28 /// БСрвис, Π² свою ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ, ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ (Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ с ошибкой),
30 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Resolve</c> Π»ΠΈΠ±ΠΎ <c>Reject</c> для оповСщСния ΠΊΠ»ΠΈΠ΅Ρ‚Π½Π° ΠΎ
29 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Resolve</c> Π»ΠΈΠ±ΠΎ <c>Reject</c> для оповСщСния ΠΊΠ»ΠΈΠ΅Ρ‚Π½Π° ΠΎ
31 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ обСщания.
30 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ обСщания.
32 /// </para>
31 /// </para>
33 /// <para>
32 /// <para>
34 /// Если сСрвСр успСл Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΅Ρ‰Π΅ Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π½Π° Π½Π΅Π³ΠΎ подписался,
33 /// Если сСрвСр успСл Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΅Ρ‰Π΅ Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π½Π° Π½Π΅Π³ΠΎ подписался,
35 /// Ρ‚ΠΎ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ подписки ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΠ²ΡƒΡŽΡ‰ΠΈΠ΅ события Π² синхронном
34 /// Ρ‚ΠΎ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ подписки ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΠ²ΡƒΡŽΡ‰ΠΈΠ΅ события Π² синхронном
36 /// Ρ€Π΅ΠΆΠΈΠΌΠ΅ ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΠΎΠ²Π΅Ρ‰Π΅Π½ Π² любом случаС. Π˜Π½Π°Ρ‡Π΅, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ΡΡ Π²
35 /// Ρ€Π΅ΠΆΠΈΠΌΠ΅ ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΠΎΠ²Π΅Ρ‰Π΅Π½ Π² любом случаС. Π˜Π½Π°Ρ‡Π΅, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ΡΡ Π²
37 /// список Π² порядкС подписания ΠΈ Π² этом ΠΆΠ΅ порядкС ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ
36 /// список Π² порядкС подписания ΠΈ Π² этом ΠΆΠ΅ порядкС ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ
38 /// обСщания.
37 /// обСщания.
39 /// </para>
38 /// </para>
40 /// <para>
39 /// <para>
41 /// ΠžΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ обСщания ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Π»ΠΈΠ±ΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ
40 /// ΠžΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ обСщания ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Π»ΠΈΠ±ΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ
42 /// связанныС асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ‚Π°ΠΊΠΆΠ΅ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ обСщания. Для этого слСдуСт
41 /// связанныС асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ‚Π°ΠΊΠΆΠ΅ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ обСщания. Для этого слСдуСт
43 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ Ρ„ΠΎΡ€ΠΌΡƒ ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ <c>Then</c>.
42 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ Ρ„ΠΎΡ€ΠΌΡƒ ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ <c>Then</c>.
44 /// </para>
43 /// </para>
45 /// <para>
44 /// <para>
46 /// Π’Π°ΠΊΠΆΠ΅ Ρ…ΠΎΡ€ΠΎΡˆΠΈΠΌ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎΠΌ являСтся Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ <c>Resolve</c> ΠΈ <c>Reject</c> Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ
45 /// Π’Π°ΠΊΠΆΠ΅ Ρ…ΠΎΡ€ΠΎΡˆΠΈΠΌ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎΠΌ являСтся Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ <c>Resolve</c> ΠΈ <c>Reject</c> Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ
47 /// Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€ обСщания ΠΈΠ½Π°Ρ‡Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ΡŒ противорСчия.
46 /// Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€ обСщания ΠΈΠ½Π°Ρ‡Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ΡŒ противорСчия.
48 /// </para>
47 /// </para>
49 /// </remarks>
48 /// </remarks>
50 public class Promise<T> : IPromise<T> {
49 public class Promise<T> : IPromise<T> {
51
50
52 protected struct HandlerDescriptor {
51 protected struct HandlerDescriptor {
53 public ResultHandler<T> resultHandler;
52 public ResultHandler<T> resultHandler;
54 public ErrorHandler<T> errorHandler;
53 public ErrorHandler<T> errorHandler;
55 public Action cancellHandler;
54 public Action cancellHandler;
56 public Promise<T> medium;
55 public Promise<T> medium;
57
56
58 public void Resolve(T result) {
57 public void Resolve(T result) {
59 if (resultHandler != null) {
58 if (resultHandler != null) {
60 try {
59 try {
61 resultHandler(result);
60 resultHandler(result);
62 } catch (Exception e) {
61 } catch (Exception e) {
63 Reject(e);
62 Reject(e);
64 return;
63 return;
65 }
64 }
66 }
65 }
67 if (medium != null)
66 if (medium != null)
68 medium.Resolve(result);
67 medium.Resolve(result);
69 }
68 }
70
69
71 public void Reject(Exception err) {
70 public void Reject(Exception err) {
72 if (errorHandler != null) {
71 if (errorHandler != null) {
73 try {
72 try {
74 var res = errorHandler(err);
73 var res = errorHandler(err);
75 if (medium != null)
74 if (medium != null)
76 medium.Resolve(res);
75 medium.Resolve(res);
77 } catch (TransientPromiseException err2) {
76 } catch (TransientPromiseException err2) {
78 if (medium != null)
77 if (medium != null)
79 medium.Reject(err2.InnerException);
78 medium.Reject(err2.InnerException);
80 } catch (Exception err2) {
79 } catch (Exception err2) {
81 if (medium != null)
80 if (medium != null)
82 medium.Reject(err2);
81 medium.Reject(err2);
83 }
82 }
84 } else if (medium != null)
83 } else if (medium != null)
85 medium.Reject(err);
84 medium.Reject(err);
86 }
85 }
87
86
88 public void Cancel() {
87 public void Cancel() {
89 if (cancellHandler != null) {
88 if (cancellHandler != null) {
90 try {
89 try {
91 cancellHandler();
90 cancellHandler();
92 } catch (Exception err) {
91 } catch (Exception err) {
93 Reject(err);
92 Reject(err);
94 return;
93 return;
95 }
94 }
96 }
95 }
97 if (medium != null)
96 if (medium != null)
98 medium.Cancel();
97 medium.Cancel();
99 }
98 }
100 }
99 }
101
100
102 const int UNRESOLVED_SATE = 0;
101 const int UNRESOLVED_SATE = 0;
103 const int TRANSITIONAL_STATE = 1;
102 const int TRANSITIONAL_STATE = 1;
104 const int SUCCEEDED_STATE = 2;
103 const int SUCCEEDED_STATE = 2;
105 const int REJECTED_STATE = 3;
104 const int REJECTED_STATE = 3;
106 const int CANCELLED_STATE = 4;
105 const int CANCELLED_STATE = 4;
107
106
108 readonly bool m_cancellable;
107 readonly bool m_cancellable;
109
108
110 int m_childrenCount = 0;
109 int m_childrenCount = 0;
111 int m_state;
110 int m_state;
112 T m_result;
111 T m_result;
113 Exception m_error;
112 Exception m_error;
114
113
115 readonly MTQueue<HandlerDescriptor> m_handlers = new MTQueue<HandlerDescriptor>();
114 readonly MTQueue<HandlerDescriptor> m_handlers = new MTQueue<HandlerDescriptor>();
116
115
117 public Promise() {
116 public Promise() {
118 m_cancellable = true;
117 m_cancellable = true;
119 }
118 }
120
119
121 public Promise(IPromise parent, bool cancellable) {
120 public Promise(IPromise parent, bool cancellable) {
122 m_cancellable = cancellable;
121 m_cancellable = cancellable;
123 if (parent != null)
122 if (parent != null)
124 Cancelled(() => {
123 AddHandler(
124 null,
125 null,
126 () => {
125 if (parent.IsExclusive)
127 if (parent.IsExclusive)
126 parent.Cancel();
128 parent.Cancel();
127 });
129 },
130 null
131 );
128 }
132 }
129
133
130 bool BeginTransit() {
134 bool BeginTransit() {
131 return UNRESOLVED_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, UNRESOLVED_SATE);
135 return UNRESOLVED_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, UNRESOLVED_SATE);
132 }
136 }
133
137
134 void CompleteTransit(int state) {
138 void CompleteTransit(int state) {
135 if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, state, TRANSITIONAL_STATE))
139 if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, state, TRANSITIONAL_STATE))
136 throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state");
140 throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state");
137 }
141 }
138
142
139 void WaitTransition() {
143 void WaitTransition() {
140 while (m_state == TRANSITIONAL_STATE) {
144 while (m_state == TRANSITIONAL_STATE) {
141 /* noop */
145 /* noop */
142 }
146 }
143 }
147 }
144
148
145 public bool IsResolved {
149 public bool IsResolved {
146 get {
150 get {
147 return m_state > 1;
151 return m_state > 1;
148 }
152 }
149 }
153 }
150
154
151 public bool IsCancelled {
155 public bool IsCancelled {
152 get {
156 get {
153 return m_state == CANCELLED_STATE;
157 return m_state == CANCELLED_STATE;
154 }
158 }
155 }
159 }
156
160
157 public Type PromiseType {
161 public Type PromiseType {
158 get { return typeof(T); }
162 get { return typeof(T); }
159 }
163 }
160
164
161 /// <summary>
165 /// <summary>
162 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ.
166 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ.
163 /// </summary>
167 /// </summary>
164 /// <param name="result">Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния.</param>
168 /// <param name="result">Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния.</param>
165 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
169 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
166 public void Resolve(T result) {
170 public void Resolve(T result) {
167 if (BeginTransit()) {
171 if (BeginTransit()) {
168 m_result = result;
172 m_result = result;
169 CompleteTransit(SUCCEEDED_STATE);
173 CompleteTransit(SUCCEEDED_STATE);
170 OnStateChanged();
174 OnStateChanged();
171 } else {
175 } else {
172 WaitTransition();
176 WaitTransition();
173 if (m_state != CANCELLED_STATE)
177 if (m_state != CANCELLED_STATE)
174 throw new InvalidOperationException("The promise is already resolved");
178 throw new InvalidOperationException("The promise is already resolved");
175 }
179 }
176 }
180 }
177
181
178 /// <summary>
182 /// <summary>
179 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ. Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ выполнСния Π±ΡƒΠ΄Π΅Ρ‚ пустоС значСния.
183 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ. Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ выполнСния Π±ΡƒΠ΄Π΅Ρ‚ пустоС значСния.
180 /// </summary>
184 /// </summary>
181 /// <remarks>
185 /// <remarks>
182 /// Π”Π°Π½Π½Ρ‹ΠΉ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ ΡƒΠ΄ΠΎΠ±Π΅Π½ Π² случаях, ΠΊΠΎΠ³Π΄Π° интСрСсСн Ρ„Π°ΠΊΡ‚ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, Π½Π΅ΠΆΠ΅Π»ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.
186 /// Π”Π°Π½Π½Ρ‹ΠΉ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ ΡƒΠ΄ΠΎΠ±Π΅Π½ Π² случаях, ΠΊΠΎΠ³Π΄Π° интСрСсСн Ρ„Π°ΠΊΡ‚ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, Π½Π΅ΠΆΠ΅Π»ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.
183 /// </remarks>
187 /// </remarks>
184 public void Resolve() {
188 public void Resolve() {
185 Resolve(default(T));
189 Resolve(default(T));
186 }
190 }
187
191
188 /// <summary>
192 /// <summary>
189 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ошибкС
193 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ошибкС
190 /// </summary>
194 /// </summary>
191 /// <remarks>
195 /// <remarks>
192 /// ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС, ΠΏΡ€ΠΈ Π΅Π³ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ сразу нСсколько ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²
196 /// ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС, ΠΏΡ€ΠΈ Π΅Π³ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ сразу нСсколько ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²
193 /// ΠΌΠΎΠ³Ρƒ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ, ΠΏΡ€ΠΈ этом Ρ‚ΠΎΠ»ΡŒΠΊΠΎ пСрвая Π±ΡƒΠ΄Π΅Ρ‚ использована Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅
197 /// ΠΌΠΎΠ³Ρƒ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ, ΠΏΡ€ΠΈ этом Ρ‚ΠΎΠ»ΡŒΠΊΠΎ пСрвая Π±ΡƒΠ΄Π΅Ρ‚ использована Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅
194 /// Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΡ€ΠΎΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹.
198 /// Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΡ€ΠΎΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹.
195 /// </remarks>
199 /// </remarks>
196 /// <param name="error">Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ</param>
200 /// <param name="error">Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ</param>
197 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
201 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
198 public void Reject(Exception error) {
202 public void Reject(Exception error) {
199 if (BeginTransit()) {
203 if (BeginTransit()) {
200 m_error = error;
204 m_error = error;
201 CompleteTransit(REJECTED_STATE);
205 CompleteTransit(REJECTED_STATE);
202 OnStateChanged();
206 OnStateChanged();
203 } else {
207 } else {
204 WaitTransition();
208 WaitTransition();
205 if (m_state == SUCCEEDED_STATE)
209 if (m_state == SUCCEEDED_STATE)
206 throw new InvalidOperationException("The promise is already resolved");
210 throw new InvalidOperationException("The promise is already resolved");
207 }
211 }
208 }
212 }
209
213
210 /// <summary>
214 /// <summary>
211 /// ΠžΡ‚ΠΌΠ΅Π½ΡΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.
215 /// ΠžΡ‚ΠΌΠ΅Π½ΡΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.
212 /// </summary>
216 /// </summary>
213 /// <returns><c>true</c> ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΡ Π±Ρ‹Π»Π° ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Π°, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π½Π΅ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹.<c>false</c> ΠΎΡ‚ΠΌΠ΅Π½Π° Π½Π΅ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π°, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ ΠΎΡ‚Ρ€Π°Π±ΠΎΡ‚Π°Π»ΠΈ.</returns>
217 /// <remarks>Для опрСдСлСния Π±Ρ‹Π»Π° Π»ΠΈ опСрация ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Π° слСдуСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ свойство <see cref="IsCancelled"/>.</remarks>
214 public bool Cancel() {
218 public void Cancel() {
215 if (m_cancellable && BeginTransit()) {
219 if (m_cancellable && BeginTransit()) {
216 CompleteTransit(CANCELLED_STATE);
220 CompleteTransit(CANCELLED_STATE);
217 OnStateChanged();
221 OnStateChanged();
218 return true;
219 }
220 return false;
221 }
222 }
222
223 // сдСлано для Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ° void
224 protected void InternalCancel() {
225 Cancel();
226 }
223 }
227
224
228
229 public IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error, Action cancel) {
225 public IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error, Action cancel) {
230 if (success == null && error == null && cancel == null)
226 if (success == null && error == null && cancel == null)
231 return this;
227 return this;
232
228
233 var medium = new Promise<T>(this, true);
229 var medium = new Promise<T>(this, true);
234
230
235 AddHandler(success, error, cancel, medium);
231 AddHandler(success, error, cancel, medium);
236
232
237 return medium;
233 return medium;
238 }
234 }
239
235
240 /// <summary>
236 /// <summary>
241 /// Adds new handlers to this promise.
237 /// Adds new handlers to this promise.
242 /// </summary>
238 /// </summary>
243 /// <param name="success">The handler of the successfully completed operation.
239 /// <param name="success">The handler of the successfully completed operation.
244 /// This handler will recieve an operation result as a parameter.</param>
240 /// This handler will recieve an operation result as a parameter.</param>
245 /// <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>
241 /// <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>
246 /// <returns>The new promise chained to this one.</returns>
242 /// <returns>The new promise chained to this one.</returns>
247 public IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error) {
243 public IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error) {
248 if (success == null && error == null)
244 if (success == null && error == null)
249 return this;
245 return this;
250
246
251 var medium = new Promise<T>(this, true);
247 var medium = new Promise<T>(this, true);
252
248
253 AddHandler(success, error, null, medium);
249 AddHandler(success, error, null, medium);
254
250
255 return medium;
251 return medium;
256 }
252 }
257
253
258 public IPromise Then(Action success, ErrorHandler error, Action cancel) {
259 return Then(
260 x => success(),
261 e => {
262 error(e);
263 return default(T);
264 },
265 cancel
266 );
267 }
268
254
269 public IPromise Then(Action success, ErrorHandler error) {
270 return Then(
271 x => success(),
272 e => {
273 error(e);
274 return default(T);
275 }
276 );
277 }
278
279 public IPromise Then(Action success) {
280 return Then(x => success());
281 }
282
255
283
256
284 public IPromise<T> Then(ResultHandler<T> success) {
257 public IPromise<T> Then(ResultHandler<T> success) {
285 if (success == null)
258 if (success == null)
286 return this;
259 return this;
287
260
288 var medium = new Promise<T>(this, true);
261 var medium = new Promise<T>(this, true);
289
262
290 AddHandler(success, null, null, medium);
263 AddHandler(success, null, null, medium);
291
264
292 return medium;
265 return medium;
293 }
266 }
294
267
268 /// <summary>
269 /// ПослСдний ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
270 /// </summary>
271 /// <param name="success"></param>
272 /// <param name="error"></param>
273 /// <param name="cancel"></param>
274 /// <remarks>
275 /// <para>
276 /// Π”Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π½Π΅ создаСт связанного с Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΌ обСщания ΠΈ ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½ для окончания
277 /// фсинхронной Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ.
278 /// </para>
279 /// <para>
280 /// Если Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ нСсколько Ρ€Π°Π·, Π»ΠΈΠ±ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, Ρ‚ΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ°
281 /// Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ΄ΠΈΠ½ΠΎΡ‡Π½ΠΎΠΉ <see cref="IsExclusive"/> ΠΈ, ΠΊΠ°ΠΊ слСдствиС, Π±ΡƒΠ΄Π΅Ρ‚ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π° ΠΎΡ‚ΠΌΠ΅Π½Π°
282 /// всСй Ρ†Π΅ΠΏΠΈ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ снизу (с самого послСднСго обСщания).
283 /// </para>
284 /// </remarks>
295 public void Last(ResultHandler<T> success, ErrorHandler error, Action cancel) {
285 public void Last(ResultHandler<T> success, ErrorHandler error, Action cancel) {
296 if (success == null && error == null && cancel == null)
286 if (success == null && error == null && cancel == null)
297 return;
287 return;
298
288
299 ErrorHandler<T> errorHandler = null;
289 ErrorHandler<T> errorHandler = null;
300 if (error != null)
290 if (error != null)
301 errorHandler = err => {
291 errorHandler = err => {
302 error(err);
292 error(err);
303 return default(T);
293 return default(T);
304 };
294 };
305 AddHandler(success, errorHandler, cancel, null);
295 AddHandler(success, errorHandler, cancel, null);
306 }
296 }
307
297
308 public void Last(ResultHandler<T> success, ErrorHandler error) {
298 public void Last(ResultHandler<T> success, ErrorHandler error) {
309 Last(success, error, null);
299 Last(success, error, null);
310 }
300 }
311
301
312 public void Last(ResultHandler<T> success) {
302 public void Last(ResultHandler<T> success) {
313 Last(success, null, null);
303 Last(success, null, null);
314 }
304 }
315
305
316 public void Last(Action success,ErrorHandler error, Action cancel) {
317 Last(x => success(), error, cancel);
318 }
319
320 public void Last(Action success,ErrorHandler error) {
321 Last(x => success(), error, null);
322 }
323
324 public void Last(Action success) {
325 Last(x => success(), null, null);
326 }
327
328 public IPromise Error(ErrorHandler error) {
306 public IPromise Error(ErrorHandler error) {
329 if (error == null)
307 if (error == null)
330 return this;
308 return this;
331
309
332 var medium = new Promise<T>(this, true);
310 var medium = new Promise<T>(this, true);
333
311
334 AddHandler(
312 AddHandler(
335 null,
313 null,
336 e => {
314 e => {
337 error(e);
315 error(e);
338 return default(T);
316 return default(T);
339 },
317 },
340 null,
318 null,
341 medium
319 medium
342 );
320 );
343
321
344 return medium;
322 return medium;
345 }
323 }
346
324
347 /// <summary>
325 /// <summary>
348 /// Handles error and allows to keep the promise.
326 /// Handles error and allows to keep the promise.
349 /// </summary>
327 /// </summary>
350 /// <remarks>
328 /// <remarks>
351 /// If the specified handler throws an exception, this exception will be used to reject the promise.
329 /// If the specified handler throws an exception, this exception will be used to reject the promise.
352 /// </remarks>
330 /// </remarks>
353 /// <param name="handler">The error handler which returns the result of the promise.</param>
331 /// <param name="handler">The error handler which returns the result of the promise.</param>
354 /// <returns>New promise.</returns>
332 /// <returns>New promise.</returns>
355 public IPromise<T> Error(ErrorHandler<T> handler) {
333 public IPromise<T> Error(ErrorHandler<T> handler) {
356 if (handler == null)
334 if (handler == null)
357 return this;
335 return this;
358
336
359 var medium = new Promise<T>(this, true);
337 var medium = new Promise<T>(this, true);
360
338
361 AddHandler(null, handler, null, medium);
339 AddHandler(null, handler, null, medium);
362
340
363 return medium;
341 return medium;
364 }
342 }
365
343
366 /// <summary>
344 /// <summary>
367 /// ΠŸΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ‚ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.
345 /// ΠŸΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ‚ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.
368 /// </summary>
346 /// </summary>
369 /// <typeparam name="TNew">Новый Ρ‚ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°.</typeparam>
347 /// <typeparam name="TNew">Новый Ρ‚ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°.</typeparam>
370 /// <param name="mapper">ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.</param>
348 /// <param name="mapper">ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.</param>
371 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
349 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
372 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
350 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
373 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ исходного обСщания.</returns>
351 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ исходного обСщания.</returns>
374 public IPromise<TNew> Then<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler<T> error) {
352 public IPromise<TNew> Then<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler<TNew> error, Action cancel) {
375 if (mapper == null)
353 Safe.ArgumentNotNull(mapper, "mapper");
376 throw new ArgumentNullException("mapper");
377
354
378 // создаСм ΠΏΡ€ΠΈΡ†Π΅ΠΏΠ»Π΅Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
355 // создаСм ΠΏΡ€ΠΈΡ†Π΅ΠΏΠ»Π΅Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
379 var chained = new Promise<TNew>(this, true);
356 var medium = new Promise<TNew>(this, true);
380
357
381 ResultHandler<T> resultHandler = result => chained.Resolve(mapper(result));
358 ResultHandler<T> resultHandler = result => medium.Resolve(mapper(result));
382 ErrorHandler<T> errorHandler;
359 ErrorHandler<T> errorHandler;
383 if (error != null)
360 if (error != null)
384 errorHandler = e => {
361 errorHandler = e => {
385 try {
362 try {
386 return error(e);
363 medium.Resolve(error(e));
387 } catch (Exception e2) {
364 } catch (Exception e2) {
388 // Π² случаС ошибки Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅
365 // Π² случаС ошибки Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅
389 chained.Reject(e2);
366 medium.Reject(e2);
390 }
367 }
391 return default(T);
368 return default(T);
392 };
369 };
393 else
370 else
394 errorHandler = e => {
371 errorHandler = e => {
395 chained.Reject(e);
372 medium.Reject(e);
396 return default(T);
373 return default(T);
397 };
374 };
398
375
376 Action cancelHandler;
377 if (cancel != null)
378 cancelHandler = () => {
379 cancel();
380 medium.Cancel();
381 };
382 else
383 cancelHandler = medium.Cancel;
384
399
385
400 AddHandler(
386 AddHandler(
401 resultHandler,
387 resultHandler,
402 errorHandler,
388 errorHandler,
403 chained.InternalCancel,
389 cancelHandler,
404 null
390 null
405 );
391 );
406
392
407 return chained;
393 return medium;
394 }
395
396 public IPromise<TNew> Then<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler<TNew> error) {
397 return Then(mapper, error, null);
408 }
398 }
409
399
410 public IPromise<TNew> Then<TNew>(ResultMapper<T, TNew> mapper) {
400 public IPromise<TNew> Then<TNew>(ResultMapper<T, TNew> mapper) {
411 return Then(mapper, null);
401 return Then(mapper, null, null);
412 }
402 }
413
403
414 /// <summary>
404 /// <summary>
415 /// БцСпляСт нСсколько аснхронных ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ. Указанная асинхронная опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½Π° послС
405 /// БцСпляСт нСсколько аснхронных ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ. Указанная асинхронная опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½Π° послС
416 /// выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ, Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ использован для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ
406 /// выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ, Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ использован для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ
417 /// Π½ΠΎΠ²ΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.
407 /// Π½ΠΎΠ²ΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.
418 /// </summary>
408 /// </summary>
419 /// <typeparam name="TNew">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</typeparam>
409 /// <typeparam name="TNew">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</typeparam>
420 /// <param name="chained">Асинхронная опСрация, которая Π΄ΠΎΠ»ΠΆΠ½Π° Π±ΡƒΠ΄Π΅Ρ‚ Π½Π°Ρ‡Π°Ρ‚ΡŒΡΡ послС выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ.</param>
410 /// <param name="chained">Асинхронная опСрация, которая Π΄ΠΎΠ»ΠΆΠ½Π° Π±ΡƒΠ΄Π΅Ρ‚ Π½Π°Ρ‡Π°Ρ‚ΡŒΡΡ послС выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ.</param>
421 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
411 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
422 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Ρ‚Π΅ΠΊΡƒΠ΅Ρ‰ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
412 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Ρ‚Π΅ΠΊΡƒΠ΅Ρ‰ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
423 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ аснхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</returns>
413 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ аснхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</returns>
424 public IPromise<TNew> Then<TNew>(ChainedOperation<T, TNew> chained, ErrorHandler<T> error) {
414 public IPromise<TNew> Chain<TNew>(ResultMapper<T, IPromise<TNew>> chained, ErrorHandler<IPromise<TNew>> error, Action cancel) {
415
416 Safe.ArgumentNotNull(chained, "chained");
425
417
426 // ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ‚ связывания Π΅Ρ‰Π΅ Π½Π΅ Π½Π°Ρ‡Π°Ρ‚Π° асинхронная опСрация, поэтому Π½ΡƒΠΆΠ½ΠΎ
418 // ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ‚ связывания Π΅Ρ‰Π΅ Π½Π΅ Π½Π°Ρ‡Π°Ρ‚Π° асинхронная опСрация, поэтому Π½ΡƒΠΆΠ½ΠΎ
427 // ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ посрСдника, ΠΊ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠΎΠ΄Π²Ρ‹Π·ΡΠ²Π°Ρ‚ΡŒΡΡ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ.
419 // ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ посрСдника, ΠΊ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠΎΠ΄Π²Ρ‹Π·ΡΠ²Π°Ρ‚ΡŒΡΡ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ.
428 // ΠΊΠΎΠ³Π΄Π° Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° Ρ€Π΅Π°Π»ΡŒΠ½Π°Ρ асинхронная опСрация, ΠΎΠ½Π° ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ ΠΊ посрСднику, Ρ‡Ρ‚ΠΎΠ±Ρ‹
420 // ΠΊΠΎΠ³Π΄Π° Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° Ρ€Π΅Π°Π»ΡŒΠ½Π°Ρ асинхронная опСрация, ΠΎΠ½Π° ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ ΠΊ посрСднику, Ρ‡Ρ‚ΠΎΠ±Ρ‹
429 // ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· Π½Π΅Π³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Ρ€Π°Π±ΠΎΡ‚Ρ‹.
421 // ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· Π½Π΅Π³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Ρ€Π°Π±ΠΎΡ‚Ρ‹.
430 var medium = new Promise<TNew>(this, true);
422 var medium = new Promise<TNew>(this, true);
431
423
432 ResultHandler<T> resultHandler = delegate(T result) {
424 ResultHandler<T> resultHandler = delegate(T result) {
433 if (medium.IsCancelled)
425 if (medium.IsCancelled)
434 return;
426 return;
435
427
436 var promise = chained(result);
428 var promise = chained(result);
437
429
438 promise.Then(
430 promise.Last(
439 medium.Resolve,
431 medium.Resolve,
440 err => {
432 medium.Reject,
441 medium.Reject(err);
433 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
442 throw new TransientPromiseException(err);
434 );
443 }
435
436 // notify chained operation that it's not needed anymore
437 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
438 // зависит IsExclusive
439 medium.Cancelled(() => {
440 if (promise.IsExclusive)
441 promise.Cancel();
442 });
443 };
444
445 ErrorHandler<T> errorHandler;
446
447 if (error != null)
448 errorHandler = delegate(Exception e) {
449 try {
450 var promise = error(e);
451
452 promise.Last(
453 medium.Resolve,
454 medium.Reject,
455 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
444 );
456 );
445
457
446 // notify chained operation that it's not needed anymore
458 // notify chained operation that it's not needed anymore
447 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
459 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
448 // зависит IsExclusive
460 // зависит IsExclusive
449 medium.Cancelled(() => {
461 medium.Cancelled(() => {
450 if (promise.IsExclusive)
462 if (promise.IsExclusive)
451 promise.Cancel();
463 promise.Cancel();
452 });
464 });
453
465 } catch (Exception e2) {
454 // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
466 medium.Reject(e2);
455 promise.Cancelled(() => medium.Reject(new OperationCanceledException()));
467 }
468 return default(T);
469 };
470 else
471 errorHandler = err => {
472 medium.Reject(err);
473 return default(T);
456 };
474 };
457
475
458 ErrorHandler<T> errorHandler = delegate(Exception e) {
476
459 if (error != null) {
477 Action cancelHandler;
460 try {
478 if (cancel != null)
461 return error(e);
479 cancelHandler = () => {
462 } catch (Exception e2) {
480 if (cancel != null)
463 medium.Reject(e2);
481 cancel();
464 return default(T);
482 medium.Cancel();
465 }
466 }
467 // Π² случаС ошибки Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅
468 medium.Reject(e);
469 return default(T);
470 };
483 };
484 else
485 cancelHandler = medium.Cancel;
471
486
472 AddHandler(
487 AddHandler(
473 resultHandler,
488 resultHandler,
474 errorHandler,
489 errorHandler,
475 medium.InternalCancel,
490 cancelHandler,
476 null
491 null
477 );
492 );
478
493
479 return medium;
494 return medium;
480 }
495 }
481
496
482 public IPromise<TNew> Then<TNew>(ChainedOperation<T, TNew> chained) {
497 public IPromise<TNew> Chain<TNew>(ResultMapper<T, IPromise<TNew>> chained, ErrorHandler<IPromise<TNew>> error) {
483 return Then(chained, null);
498 return Chain(chained, error, null);
499 }
500
501 public IPromise<TNew> Chain<TNew>(ResultMapper<T, IPromise<TNew>> chained) {
502 return Chain(chained, null, null);
484 }
503 }
485
504
486 public IPromise<T> Cancelled(Action handler) {
505 public IPromise<T> Cancelled(Action handler) {
487 var medium = new Promise<T>(this, true);
506 var medium = new Promise<T>(this,true);
488 AddHandler(null, null, handler, medium);
507 AddHandler(null, null, handler, medium);
489 return medium;
508 return medium;
490 }
509 }
491
510
492 /// <summary>
511 /// <summary>
493 /// Adds the specified handler for all cases (success, error, cancel)
512 /// Adds the specified handler for all cases (success, error, cancel)
494 /// </summary>
513 /// </summary>
495 /// <param name="handler">The handler that will be called anyway</param>
514 /// <param name="handler">The handler that will be called anyway</param>
496 /// <returns>self</returns>
515 /// <returns>self</returns>
497 public IPromise<T> Finally(Action handler) {
516 public IPromise<T> Anyway(Action handler) {
498 if (handler == null)
517 Safe.ArgumentNotNull(handler, "handler");
499 throw new ArgumentNullException("handler");
518
500 AddHandler(
519 AddHandler(
501 x => handler(),
520 x => handler(),
502 e => {
521 e => {
503 handler();
522 handler();
504 throw new TransientPromiseException(e);
523 throw new TransientPromiseException(e);
505 },
524 },
506 handler,
525 handler,
507 null
526 null
508 );
527 );
509 return this;
528 return this;
510 }
529 }
511
530
512 /// <summary>
531 /// <summary>
513 /// ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ обСщания ΠΊ Π½ΡƒΠΆΠ½ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ
532 /// ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ обСщания ΠΊ Π½ΡƒΠΆΠ½ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ
514 /// </summary>
533 /// </summary>
515 /// <typeparam name="T2"></typeparam>
534 /// <typeparam name="T2"></typeparam>
516 /// <returns></returns>
535 /// <returns></returns>
517 public IPromise<T2> Cast<T2>() {
536 public IPromise<T2> Cast<T2>() {
518 return Then(x => (T2)(object)x, null);
537 return Then(x => (T2)(object)x, null);
519 }
538 }
520
539
521 /// <summary>
540 /// <summary>
522 /// ДоТидаСтся ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ³ΠΎ обСщания ΠΈ Π² случаС успСха, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚
541 /// ДоТидаСтся ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ³ΠΎ обСщания ΠΈ Π² случаС успСха, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚
523 /// Π΅Π³ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС бросаСт ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.
542 /// Π΅Π³ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС бросаСт ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.
524 /// </summary>
543 /// </summary>
525 /// <remarks>
544 /// <remarks>
526 /// <para>
545 /// <para>
527 /// Если ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ обСщания Π±Ρ‹Π»ΠΎ ΠΏΡ€Π΅Ρ€Π²Π°Π½ΠΎ ΠΏΠΎ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚Ρƒ, это Π½Π΅ Π·Π½Π°Ρ‡ΠΈΡ‚,
546 /// Если ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ обСщания Π±Ρ‹Π»ΠΎ ΠΏΡ€Π΅Ρ€Π²Π°Π½ΠΎ ΠΏΠΎ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚Ρƒ, это Π½Π΅ Π·Π½Π°Ρ‡ΠΈΡ‚,
528 /// Ρ‡Ρ‚ΠΎ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±Ρ‹Π»ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½ΠΎ ΠΈΠ»ΠΈ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π² этом Ρ€ΠΎΠ΄Π΅, это Ρ‚ΠΎΠ»ΡŒΠΊΠΎ
547 /// Ρ‡Ρ‚ΠΎ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±Ρ‹Π»ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½ΠΎ ΠΈΠ»ΠΈ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π² этом Ρ€ΠΎΠ΄Π΅, это Ρ‚ΠΎΠ»ΡŒΠΊΠΎ
529 /// ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π΅Π³ΠΎ Π½Π΅ доТдались, ΠΎΠ΄Π½Π°ΠΊΠΎ всС зарСгистрированныС
548 /// ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π΅Π³ΠΎ Π½Π΅ доТдались, ΠΎΠ΄Π½Π°ΠΊΠΎ всС зарСгистрированныС
530 /// ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, ΠΊΠ°ΠΊ Π±Ρ‹Π»ΠΈ Ρ‚Π°ΠΊ ΠΎΡΡ‚Π°Π»ΠΈΡΡŒ ΠΈ ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹, ΠΊΠΎΠ³Π΄Π°
549 /// ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, ΠΊΠ°ΠΊ Π±Ρ‹Π»ΠΈ Ρ‚Π°ΠΊ ΠΎΡΡ‚Π°Π»ΠΈΡΡŒ ΠΈ ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹, ΠΊΠΎΠ³Π΄Π°
531 /// ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
550 /// ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
532 /// </para>
551 /// </para>
533 /// <para>
552 /// <para>
534 /// Π’Π°ΠΊΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π²ΠΏΠΎΠ»Π½Π΅ ΠΎΠΏΡ€Π°Π²Π΄Π°Π½ΠΎ ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΡ‚Π΅Ρ‡ΡŒ
553 /// Π’Π°ΠΊΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π²ΠΏΠΎΠ»Π½Π΅ ΠΎΠΏΡ€Π°Π²Π΄Π°Π½ΠΎ ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΡ‚Π΅Ρ‡ΡŒ
535 /// Π² Ρ‚ΠΎΡ‚ ΠΌΠΎΠΌΠ΅Π½Ρ‚, ΠΊΠΎΠ³Π΄Π° Π½Π°Ρ‡Π°Π»Π°ΡΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ², ΠΈ
554 /// Π² Ρ‚ΠΎΡ‚ ΠΌΠΎΠΌΠ΅Π½Ρ‚, ΠΊΠΎΠ³Π΄Π° Π½Π°Ρ‡Π°Π»Π°ΡΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ², ΠΈ
536 /// ΠΊ Ρ‚ΠΎΠΌΡƒ ΠΆΠ΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡ‚ΠΎΡΡ‚ΡŒ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ ΠΈ Π΅Π³ΠΎ
555 /// ΠΊ Ρ‚ΠΎΠΌΡƒ ΠΆΠ΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡ‚ΠΎΡΡ‚ΡŒ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ ΠΈ Π΅Π³ΠΎ
537 /// ΠΎΡ‚ΠΊΠ»ΠΎΠ½Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ Π½Π΅ΠΏΡ€ΠΎΠ³Π½ΠΎΠ·ΠΈΡ€ΡƒΠ΅ΠΌΠΎΠΌΡƒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρƒ.
556 /// ΠΎΡ‚ΠΊΠ»ΠΎΠ½Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ Π½Π΅ΠΏΡ€ΠΎΠ³Π½ΠΎΠ·ΠΈΡ€ΡƒΠ΅ΠΌΠΎΠΌΡƒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρƒ.
538 /// </para>
557 /// </para>
539 /// </remarks>
558 /// </remarks>
540 /// <param name="timeout">ВрСмя оТидания</param>
559 /// <param name="timeout">ВрСмя оТидания</param>
541 /// <returns>Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния обСщания</returns>
560 /// <returns>Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния обСщания</returns>
542 public T Join(int timeout) {
561 public T Join(int timeout) {
543 var evt = new ManualResetEvent(false);
562 var evt = new ManualResetEvent(false);
544 Finally(() => evt.Set());
563 Anyway(() => evt.Set());
545
564
546 if (!evt.WaitOne(timeout, true))
565 if (!evt.WaitOne(timeout, true))
547 throw new TimeoutException();
566 throw new TimeoutException();
548
567
549 switch (m_state) {
568 switch (m_state) {
550 case SUCCEEDED_STATE:
569 case SUCCEEDED_STATE:
551 return m_result;
570 return m_result;
552 case CANCELLED_STATE:
571 case CANCELLED_STATE:
553 throw new OperationCanceledException();
572 throw new OperationCanceledException();
554 case REJECTED_STATE:
573 case REJECTED_STATE:
555 throw new TargetInvocationException(m_error);
574 throw new TargetInvocationException(m_error);
556 default:
575 default:
557 throw new ApplicationException(String.Format("Invalid promise state {0}", m_state));
576 throw new ApplicationException(String.Format("Invalid promise state {0}", m_state));
558 }
577 }
559 }
578 }
560
579
561 public T Join() {
580 public T Join() {
562 return Join(Timeout.Infinite);
581 return Join(Timeout.Infinite);
563 }
582 }
564
583
565 void AddHandler(ResultHandler<T> success, ErrorHandler<T> error, Action cancel, Promise<T> medium) {
584 void AddHandler(ResultHandler<T> success, ErrorHandler<T> error, Action cancel, Promise<T> medium) {
566 if (success != null || error != null)
585 if (success != null || error != null)
567 Interlocked.Increment(ref m_childrenCount);
586 Interlocked.Increment(ref m_childrenCount);
568
587
569 var handler = new HandlerDescriptor {
588 var handler = new HandlerDescriptor {
570 resultHandler = success,
589 resultHandler = success,
571 errorHandler = error,
590 errorHandler = error,
572 cancellHandler = cancel,
591 cancellHandler = cancel,
573 medium = medium
592 medium = medium
574 };
593 };
575
594
576 bool queued;
595 bool queued;
577
596
578 if (!IsResolved) {
597 if (!IsResolved) {
579 m_handlers.Enqueue(handler);
598 m_handlers.Enqueue(handler);
580 queued = true;
599 queued = true;
581 } else {
600 } else {
582 // the promise is in resolved state, just invoke the handled with minimum overhead
601 // the promise is in resolved state, just invoke the handled with minimum overhead
583 queued = false;
602 queued = false;
584 InvokeHandler(handler);
603 InvokeHandler(handler);
585 }
604 }
586
605
587 if (queued && IsResolved && m_handlers.TryDequeue(out handler))
606 if (queued && IsResolved && m_handlers.TryDequeue(out handler))
588 // if the promise have been resolved while we was adding handler to the queue
607 // if the promise have been resolved while we was adding handler to the queue
589 // we can't guarantee that someone is still processing it
608 // we can't guarantee that someone is still processing it
590 // therefore we will fetch a handler from the queue and execute it
609 // therefore we will fetch a handler from the queue and execute it
591 // note that fetched handler may be not the one that we have added
610 // note that fetched handler may be not the one that we have added
592 // even we can fetch no handlers at all :)
611 // even we can fetch no handlers at all :)
593 InvokeHandler(handler);
612 InvokeHandler(handler);
594 }
613 }
595
614
596 protected virtual void InvokeHandler(HandlerDescriptor handler) {
615 protected virtual void InvokeHandler(HandlerDescriptor handler) {
597 switch (m_state) {
616 switch (m_state) {
598 case SUCCEEDED_STATE:
617 case SUCCEEDED_STATE:
599 handler.Resolve(m_result);
618 handler.Resolve(m_result);
600 break;
619 break;
601 case REJECTED_STATE:
620 case REJECTED_STATE:
602 handler.Reject(m_error);
621 handler.Reject(m_error);
603 break;
622 break;
604 case CANCELLED_STATE:
623 case CANCELLED_STATE:
605 handler.Cancel();
624 handler.Cancel();
606 break;
625 break;
607 default:
626 default:
608 // do nothing
627 // do nothing
609 return;
628 return;
610 }
629 }
611 }
630 }
612
631
613 void OnStateChanged() {
632 void OnStateChanged() {
614 HandlerDescriptor handler;
633 HandlerDescriptor handler;
615 while (m_handlers.TryDequeue(out handler))
634 while (m_handlers.TryDequeue(out handler))
616 InvokeHandler(handler);
635 InvokeHandler(handler);
617 }
636 }
618
637
619 public bool IsExclusive {
638 public bool IsExclusive {
620 get {
639 get {
621 return m_childrenCount <= 1;
640 return m_childrenCount <= 1;
622 }
641 }
623 }
642 }
624
643
625 /// <summary>
644 /// <summary>
626 /// ΠžΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ нСсколько ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ являСтся массив Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
645 /// ΠžΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ нСсколько ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ являСтся массив Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
627 /// Если хотябы ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚ΠΎ Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ Ρ‚ΠΎΠΆΠ΅ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
646 /// Если хотябы ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚ΠΎ Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ Ρ‚ΠΎΠΆΠ΅ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
628 /// ΠŸΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ Π½ΠΎΠ²ΠΎΠ³ΠΎ обСщания, ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅ обСщания Ρ‚Π°ΠΊΠΆΠ΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Ρ‹, Ссли Π½ΠΈΠΊΡ‚ΠΎ большС Π½Π° Π½ΠΈΡ… Π½Π΅ подписан.
647 /// ΠŸΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ Π½ΠΎΠ²ΠΎΠ³ΠΎ обСщания, ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅ обСщания Ρ‚Π°ΠΊΠΆΠ΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Ρ‹, Ссли Π½ΠΈΠΊΡ‚ΠΎ большС Π½Π° Π½ΠΈΡ… Π½Π΅ подписан.
629 /// </summary>
648 /// </summary>
630 /// <param name="promises">Бписок ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ. Если список пустой, Ρ‚ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ возвращаСтся ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹ΠΌ.</param>
649 /// <param name="promises">Бписок ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ. Если список пустой, Ρ‚ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ возвращаСтся ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹ΠΌ.</param>
631 /// <returns>ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰Π΅Π΅ Π² сСбС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.</returns>
650 /// <returns>ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰Π΅Π΅ Π² сСбС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.</returns>
632 /// <exception cref="ArgumentNullException"><paramref name="promises"/> Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ null</exception>
651 /// <exception cref="ArgumentNullException"><paramref name="promises"/> Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ null</exception>
633 public static IPromise<T[]> CreateComposite(IList<IPromise<T>> promises) {
652 public static IPromise<T[]> CreateComposite(IList<IPromise<T>> promises) {
634 if (promises == null)
653 if (promises == null)
635 throw new ArgumentNullException();
654 throw new ArgumentNullException();
636
655
637 // создаСм аккумулятор для Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² ΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
656 // создаСм аккумулятор для Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² ΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
638 var result = new T[promises.Count];
657 var result = new T[promises.Count];
639 var promise = new Promise<T[]>();
658 var promise = new Promise<T[]>();
640
659
641 // special case
660 // special case
642 if (promises.Count == 0) {
661 if (promises.Count == 0) {
643 promise.Resolve(result);
662 promise.Resolve(result);
644 return promise;
663 return promise;
645 }
664 }
646
665
647 int pending = promises.Count;
666 int pending = promises.Count;
648
667
649 for (int i = 0; i < promises.Count; i++) {
668 for (int i = 0; i < promises.Count; i++) {
650 var dest = i;
669 var dest = i;
651
670
652 if (promises[i] != null) {
671 if (promises[i] != null) {
653 promises[i].Then(
672 promises[i].Then(
654 x => {
673 x => {
655 result[dest] = x;
674 result[dest] = x;
656 if (Interlocked.Decrement(ref pending) == 0)
675 if (Interlocked.Decrement(ref pending) == 0)
657 promise.Resolve(result);
676 promise.Resolve(result);
658 },
677 },
659 e => {
678 e => {
660 promise.Reject(e);
679 promise.Reject(e);
661 return default(T);
680 return default(T);
662 }
681 }
663 );
682 );
664 } else {
683 } else {
665 if (Interlocked.Decrement(ref pending) == 0)
684 if (Interlocked.Decrement(ref pending) == 0)
666 promise.Resolve(result);
685 promise.Resolve(result);
667 }
686 }
668 }
687 }
669
688
670 promise.Cancelled(
689 promise.Cancelled(
671 () => {
690 () => {
672 foreach (var d in promises)
691 foreach (var d in promises)
673 if (d != null && d.IsExclusive)
692 if (d != null && d.IsExclusive)
674 d.Cancel();
693 d.Cancel();
675 }
694 }
676 );
695 );
677
696
678 return promise;
697 return promise;
679 }
698 }
680
699
681 /// <summary>
700 /// <summary>
682 /// ΠžΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ нСсколько ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ. Π Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ
701 /// ΠžΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ нСсколько ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ. Π Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ
683 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ всСх ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ. ΠŸΡ€ΠΈ этом Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹Π΅ значСния ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ
702 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ всСх ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ. ΠŸΡ€ΠΈ этом Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹Π΅ значСния ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ
684 /// ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΡƒΡŽΡ‚ΡΡ.
703 /// ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΡƒΡŽΡ‚ΡΡ.
685 /// </summary>
704 /// </summary>
686 /// <param name="promises">ΠšΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΡ ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΠ±ΡŠΠ΅Π΄Π΅Π½Π΅Π½Ρ‹ Π² ΠΎΠ΄Π½ΠΎ.</param>
705 /// <param name="promises">ΠšΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΡ ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΠ±ΡŠΠ΅Π΄Π΅Π½Π΅Π½Ρ‹ Π² ΠΎΠ΄Π½ΠΎ.</param>
687 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰Π΅Π΅ Π² сСбС ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅.</returns>
706 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰Π΅Π΅ Π² сСбС ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅.</returns>
688 /// <remarks>
707 /// <remarks>
689 /// Если Π² ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΈ Π²ΡΡ‚Ρ€Π΅Ρ‡Π°ΡŽΡŒΡΡ <c>null</c>, Ρ‚ΠΎ ΠΎΠ½ΠΈ Π²ΠΎΡΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹Π΅ обСщания.
708 /// Если Π² ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΈ Π²ΡΡ‚Ρ€Π΅Ρ‡Π°ΡŽΡŒΡΡ <c>null</c>, Ρ‚ΠΎ ΠΎΠ½ΠΈ Π²ΠΎΡΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹Π΅ обСщания.
690 /// </remarks>
709 /// </remarks>
691 public static IPromise CreateComposite(ICollection<IPromise> promises) {
710 public static IPromise CreateComposite(ICollection<IPromise> promises) {
692 if (promises == null)
711 if (promises == null)
693 throw new ArgumentNullException();
712 throw new ArgumentNullException();
694 if (promises.Count == 0)
713 if (promises.Count == 0)
695 return Promise<object>.ResultToPromise(null);
714 return Promise<object>.ResultToPromise(null);
696
715
697 int countdown = promises.Count;
716 int countdown = promises.Count;
698
717
699 var result = new Promise<object>();
718 var result = new Promise<object>();
700
719
701 foreach (var d in promises) {
720 foreach (var d in promises) {
702 if (d == null) {
721 if (d == null) {
703 if (Interlocked.Decrement(ref countdown) == 0)
722 if (Interlocked.Decrement(ref countdown) == 0)
704 result.Resolve(null);
723 result.Resolve(null);
705 } else {
724 } else {
706 d.Then(() => {
725 d.Then(() => {
707 if (Interlocked.Decrement(ref countdown) == 0)
726 if (Interlocked.Decrement(ref countdown) == 0)
708 result.Resolve(null);
727 result.Resolve(null);
709 });
728 });
710 }
729 }
711 }
730 }
712
731
713 result.Cancelled(() => {
732 result.Cancelled(() => {
714 foreach (var d in promises)
733 foreach (var d in promises)
715 if (d != null && d.IsExclusive)
734 if (d != null && d.IsExclusive)
716 d.Cancel();
735 d.Cancel();
717 });
736 });
718
737
719 return result;
738 return result;
720 }
739 }
721
740
722 public static Promise<T> ResultToPromise(T result) {
741 public static Promise<T> ResultToPromise(T result) {
723 var p = new Promise<T>();
742 var p = new Promise<T>();
724 p.Resolve(result);
743 p.Resolve(result);
725 return p;
744 return p;
726 }
745 }
727
746
728 public static Promise<T> ExceptionToPromise(Exception error) {
747 public static Promise<T> ExceptionToPromise(Exception error) {
729 if (error == null)
748 if (error == null)
730 throw new ArgumentNullException();
749 throw new ArgumentNullException();
731
750
732 var p = new Promise<T>();
751 var p = new Promise<T>();
733 p.Reject(error);
752 p.Reject(error);
734 return p;
753 return p;
735 }
754 }
736
755
737 #region IPromiseBase explicit implementation
756 #region IPromiseBase explicit implementation
738
757
758 IPromise IPromise.Then(Action success, ErrorHandler error, Action cancel) {
759 return Then(
760 x => success(),
761 e => {
762 error(e);
763 return default(T);
764 },
765 cancel
766 );
767 }
768
769 IPromise IPromise.Then(Action success, ErrorHandler error) {
770 return Then(
771 x => success(),
772 e => {
773 error(e);
774 return default(T);
775 }
776 );
777 }
778
779 IPromise IPromise.Then(Action success) {
780 return Then(x => success());
781 }
782
783 void IPromise.Last(Action success, ErrorHandler error, Action cancel) {
784 Last(x => success(), error, cancel);
785 }
786
787 void IPromise.Last(Action success, ErrorHandler error) {
788 Last(x => success(), error, null);
789 }
790
791 void IPromise.Last(Action success) {
792 Last(x => success(), null, null);
793 }
794
739 IPromise IPromise.Error(ErrorHandler error) {
795 IPromise IPromise.Error(ErrorHandler error) {
740 return Error(error);
796 return Error(error);
741 }
797 }
742
798
743 IPromise IPromise.Finally(Action handler) {
799 IPromise IPromise.Anyway(Action handler) {
744 return Finally(handler);
800 return Anyway(handler);
745 }
801 }
746
802
747 IPromise IPromise.Cancelled(Action handler) {
803 IPromise IPromise.Cancelled(Action handler) {
748 return Cancelled(handler);
804 return Cancelled(handler);
749 }
805 }
750
806
751 void IPromise.Join() {
807 void IPromise.Join() {
752 Join();
808 Join();
753 }
809 }
754
810
755 void IPromise.Join(int timeout) {
811 void IPromise.Join(int timeout) {
756 Join(timeout);
812 Join(timeout);
757 }
813 }
758
814
759 #endregion
815 #endregion
760
816
761
817
762
818
763 }
819 }
764 }
820 }
@@ -1,69 +1,65
1 using System.Threading;
1 using System.Threading;
2 using System;
2 using System;
3 #if NET_4_5
3 #if NET_4_5
4 using System.Threading.Tasks;
4 using System.Threading.Tasks;
5 #endif
5 #endif
6
6
7 namespace Implab {
7 namespace Implab {
8 public static class PromiseExtensions {
8 public static class PromiseExtensions {
9 public static IPromise<T> DispatchToCurrentContext<T>(this IPromise<T> that) {
9 public static IPromise<T> DispatchToCurrentContext<T>(this IPromise<T> that) {
10 Safe.ArgumentNotNull(that, "that");
10 Safe.ArgumentNotNull(that, "that");
11 var context = SynchronizationContext.Current;
11 var context = SynchronizationContext.Current;
12 if (context == null)
12 if (context == null)
13 return that;
13 return that;
14
14
15 var p = new SyncContextPromise<T>(context, that, true);
15 var p = new SyncContextPromise<T>(context, that, true);
16
16
17 that.Then(
17 that.Last(
18 x => p.Resolve(x),
18 p.Resolve,
19 e => {
19 p.Reject,
20 p.Reject(e);
20 p.Cancel
21 return default(T);
22 }
23 );
21 );
24 return p;
22 return p;
25 }
23 }
26
24
27 public static IPromise<T> DispatchToContext<T>(this IPromise<T> that, SynchronizationContext context) {
25 public static IPromise<T> DispatchToContext<T>(this IPromise<T> that, SynchronizationContext context) {
28 Safe.ArgumentNotNull(that, "that");
26 Safe.ArgumentNotNull(that, "that");
29 Safe.ArgumentNotNull(context, "context");
27 Safe.ArgumentNotNull(context, "context");
30
28
31 var p = new SyncContextPromise<T>(context, that, true);
29 var p = new SyncContextPromise<T>(context, that, true);
32
30
33 that.Then(
31 that.Last(
34 x => p.Resolve(x),
32 p.Resolve,
35 e => {
33 p.Reject,
36 p.Reject(e);
34 p.Cancel
37 return default(T);
38 }
39 );
35 );
40 return p;
36 return p;
41 }
37 }
42
38
43 public static AsyncCallback AsyncCallback<T>(this Promise<T> that, Func<IAsyncResult,T> callback) {
39 public static AsyncCallback AsyncCallback<T>(this Promise<T> that, Func<IAsyncResult,T> callback) {
44 Safe.ArgumentNotNull(that, "that");
40 Safe.ArgumentNotNull(that, "that");
45 Safe.ArgumentNotNull(callback, "callback");
41 Safe.ArgumentNotNull(callback, "callback");
46 return ar => {
42 return ar => {
47 try {
43 try {
48 that.Resolve(callback(ar));
44 that.Resolve(callback(ar));
49 } catch (Exception err) {
45 } catch (Exception err) {
50 that.Reject(err);
46 that.Reject(err);
51 }
47 }
52 };
48 };
53 }
49 }
54
50
55 #if NET_4_5
51 #if NET_4_5
56
52
57 public static Task<T> GetTask<T>(this IPromise<T> that) {
53 public static Task<T> GetTask<T>(this IPromise<T> that) {
58 Safe.ArgumentNotNull(that, "that");
54 Safe.ArgumentNotNull(that, "that");
59 var tcs = new TaskCompletionSource<T>();
55 var tcs = new TaskCompletionSource<T>();
60
56
61 that.Last(tcs.SetResult, tcs.SetException, tcs.SetCanceled);
57 that.Last(tcs.SetResult, tcs.SetException, tcs.SetCanceled);
62
58
63 return tcs.Task;
59 return tcs.Task;
64 }
60 }
65
61
66 #endif
62 #endif
67 }
63 }
68 }
64 }
69
65
@@ -1,27 +1,27
1 using System.Reflection;
1 using System.Reflection;
2 using System.Runtime.CompilerServices;
2 using System.Runtime.CompilerServices;
3 using System.Runtime.InteropServices;
3 using System.Runtime.InteropServices;
4
4
5 // Information about this assembly is defined by the following attributes.
5 // Information about this assembly is defined by the following attributes.
6 // Change them to the values specific to your project.
6 // Change them to the values specific to your project.
7
7
8 [assembly: AssemblyTitle("Implab")]
8 [assembly: AssemblyTitle("Implab")]
9 [assembly: AssemblyDescription("Tools")]
9 [assembly: AssemblyDescription("Tools")]
10 [assembly: AssemblyConfiguration("")]
10 [assembly: AssemblyConfiguration("")]
11 [assembly: AssemblyCompany("")]
11 [assembly: AssemblyCompany("")]
12 [assembly: AssemblyProduct("")]
12 [assembly: AssemblyProduct("")]
13 [assembly: AssemblyCopyright("Implab")]
13 [assembly: AssemblyCopyright("Implab")]
14 [assembly: AssemblyTrademark("")]
14 [assembly: AssemblyTrademark("")]
15 // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
15 // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
16 // The form "{Major}.{Minor}.*" will automatically update the build and revision,
16 // The form "{Major}.{Minor}.*" will automatically update the build and revision,
17 // and "{Major}.{Minor}.{Build}.*" will update just the revision.
17 // and "{Major}.{Minor}.{Build}.*" will update just the revision.
18
18
19 [assembly: AssemblyVersion("1.0.*")]
19 [assembly: AssemblyVersion("2.0.*")]
20 [assembly: ComVisible(false)]
20 [assembly: ComVisible(false)]
21
21
22 // The following attributes are used to specify the signing key for the assembly,
22 // The following attributes are used to specify the signing key for the assembly,
23 // if desired. See the Mono documentation for more information about signing.
23 // if desired. See the Mono documentation for more information about signing.
24
24
25 //[assembly: AssemblyDelaySign(false)]
25 //[assembly: AssemblyDelaySign(false)]
26 //[assembly: AssemblyKeyFile("")]
26 //[assembly: AssemblyKeyFile("")]
27
27
@@ -1,140 +1,136
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
3 using System.Linq;
4 using System.Text;
4 using System.Text;
5 using System.Threading;
5 using System.Threading;
6
6
7 namespace Implab
7 namespace Implab
8 {
8 {
9 /// <summary>
9 /// <summary>
10 /// This class allows to interact with asyncronuos task.
10 /// This class allows to interact with asyncronuos task.
11 /// </summary>
11 /// </summary>
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 public 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;
19
19
20 float m_current;
20 float m_current;
21 float m_max;
21 float m_max;
22
22
23 bool m_cancelled;
23 bool m_cancelled;
24
24
25 public event EventHandler Cancelled;
25 public event EventHandler Cancelled;
26 public event EventHandler<ValueEventArgs<string>> MessageUpdated;
26 public event EventHandler<ValueEventArgs<string>> MessageUpdated;
27 public event EventHandler<ValueEventArgs<float>> ProgressUpdated;
27 public event EventHandler<ValueEventArgs<float>> ProgressUpdated;
28 public event EventHandler<ProgressInitEventArgs> ProgressInit;
28 public event EventHandler<ProgressInitEventArgs> ProgressInit;
29
29
30 public TaskController()
30 public TaskController()
31 {
31 {
32 m_lock = new Object();
32 m_lock = new Object();
33 }
33 }
34
34
35 public string Message
35 public string Message
36 {
36 {
37 get
37 get
38 {
38 {
39 lock (m_lock)
39 lock (m_lock)
40 return m_message;
40 return m_message;
41 }
41 }
42 set
42 set
43 {
43 {
44 lock (m_lock)
44 lock (m_lock)
45 {
45 {
46 m_message = value;
46 m_message = value;
47 OnMessageUpdated();
47 OnMessageUpdated();
48 }
48 }
49 }
49 }
50 }
50 }
51
51
52 public float CurrentProgress
52 public float CurrentProgress
53 {
53 {
54 get
54 get
55 {
55 {
56 lock (m_lock)
56 lock (m_lock)
57 return m_current;
57 return m_current;
58 }
58 }
59 set
59 set
60 {
60 {
61 lock (m_lock)
61 lock (m_lock)
62 {
62 {
63 var prev = m_current;
63 var prev = m_current;
64 m_current = value;
64 m_current = value;
65 if (m_current >= m_max)
65 if (m_current >= m_max)
66 m_current = m_max;
66 m_current = m_max;
67 if (m_current != prev)
67 if (m_current != prev)
68 OnProgressUpdated();
68 OnProgressUpdated();
69 }
69 }
70 }
70 }
71 }
71 }
72
72
73 public void InitProgress(float current, float max, string message)
73 public void InitProgress(float current, float max, string message)
74 {
74 {
75 if (max < 0)
75 if (max < 0)
76 throw new ArgumentOutOfRangeException("max");
76 throw new ArgumentOutOfRangeException("max");
77 if (current < 0 || current > max)
77 if (current < 0 || current > max)
78 throw new ArgumentOutOfRangeException("current");
78 throw new ArgumentOutOfRangeException("current");
79
79
80 lock(m_lock) {
80 lock(m_lock) {
81 m_current = current;
81 m_current = current;
82 m_max = max;
82 m_max = max;
83 m_message = message;
83 m_message = message;
84 OnProgressInit();
84 OnProgressInit();
85 }
85 }
86 }
86 }
87
87
88 public bool IsCancelled {
88 public bool IsCancelled {
89 get {
89 get {
90 lock (m_lock)
90 lock (m_lock)
91 return m_cancelled;
91 return m_cancelled;
92 }
92 }
93 }
93 }
94
94
95 public bool Cancel() {
95 public void Cancel() {
96 lock (m_lock) {
96 lock (m_lock) {
97 if (!m_cancelled) {
97 if (!m_cancelled)
98 m_cancelled = true;
98 m_cancelled = true;
99 return true;
100 } else {
101 return false;
102 }
103 }
99 }
104 }
100 }
105
101
106 protected virtual void OnCancelled() {
102 protected virtual void OnCancelled() {
107 var temp = Cancelled;
103 var temp = Cancelled;
108 if (temp != null) {
104 if (temp != null) {
109 temp(this,new EventArgs());
105 temp(this,new EventArgs());
110 }
106 }
111 }
107 }
112
108
113 protected virtual void OnMessageUpdated()
109 protected virtual void OnMessageUpdated()
114 {
110 {
115 var temp = MessageUpdated;
111 var temp = MessageUpdated;
116 if (temp != null)
112 if (temp != null)
117 {
113 {
118 temp(this, new ValueEventArgs<string>(m_message));
114 temp(this, new ValueEventArgs<string>(m_message));
119 }
115 }
120 }
116 }
121
117
122 protected virtual void OnProgressUpdated()
118 protected virtual void OnProgressUpdated()
123 {
119 {
124 var temp = ProgressUpdated;
120 var temp = ProgressUpdated;
125 if (temp != null)
121 if (temp != null)
126 {
122 {
127 temp(this,new ValueEventArgs<float>(m_current));
123 temp(this,new ValueEventArgs<float>(m_current));
128 }
124 }
129 }
125 }
130
126
131 protected virtual void OnProgressInit()
127 protected virtual void OnProgressInit()
132 {
128 {
133 var temp = ProgressInit;
129 var temp = ProgressInit;
134 if (temp != null)
130 if (temp != null)
135 {
131 {
136 temp(this, new ProgressInitEventArgs(m_current,m_max, m_message));
132 temp(this, new ProgressInitEventArgs(m_current,m_max, m_message));
137 }
133 }
138 }
134 }
139 }
135 }
140 }
136 }
General Comments 0
You need to be logged in to leave comments. Login now