##// END OF EJS Templates
added memory barriers
cin -
r80:4f20870d0816 v2
parent child
Show More
@@ -0,0 +1,85
1 using System;
2 using Implab.Parallels;
3 using System.Threading;
4
5 namespace Implab {
6 /*public class SyncPool<T> : IDisposable {
7 readonly Func<T> m_factory;
8 readonly Action<T> m_cleanup;
9 readonly int m_size;
10 readonly MTQueue<T> m_queue = new MTQueue<T>();
11
12 volatile bool m_disposed;
13
14 volatile int m_count;
15
16 public SyncPool(Func<T> factory, Action<T> cleanup, int size) {
17 Safe.ArgumentNotNull(factory, "factory");
18 Safe.ArgumentInRange(size, 1, size, "size");
19
20 m_factory = factory;
21 m_cleanup = cleanup;
22 m_size = size;
23 }
24
25 public SyncPool(Func<T> factory, Action<T> cleanup) : this(factory,cleanup,Environment.ProcessorCount+1) {
26 }
27
28 public SyncPool(Func<T> factory) : this(factory,null,Environment.ProcessorCount+1) {
29 }
30
31 public SyncPoolWrapper<T> Allocate() {
32 if (m_disposed)
33 throw new ObjectDisposedException(this.ToString());
34
35 T instance;
36 if (m_queue.TryDequeue(out instance)) {
37 Interlocked.Decrement(ref m_count);
38 return instance;
39 } else {
40 instance = m_factory();
41 }
42 return new SyncPoolWrapper<T>(instance, this);
43 }
44
45 public void Release(T instance) {
46 if (m_count < m_size && !m_disposed) {
47 Interlocked.Increment(ref m_count);
48
49 if (m_cleanup != null)
50 m_cleanup(instance);
51
52 m_queue.Enqueue(instance);
53
54 // ΠΏΠΎΠΊΠ° элСмСнт возвращался Π² кСш, Π±Ρ‹Π»Π° Π½Π°Ρ‡Π°Ρ‚Π° опСрация освобоТдСния всСго кСша
55 // ΠΈ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ ΡƒΠΆΠ΅ Π·Π°ΠΊΠΎΠ½Ρ†Π΅Π½Π°, Π² Ρ‚Π°ΠΊΠΎΠΌ случаС слСдуСт ΠΈΠ·Π²Π»Π΅Ρ‡ΡŒ элСмСнт ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ ΠΈ
56 // ΠΎΡΠ²ΠΎΠ±ΠΎΠ΄ΠΈΡ‚ΡŒ Π΅Π³ΠΎ. Если опСрация освобоТдСния кСша Π΅Ρ‰Π΅ Π½Π΅ Π·Π°Π²Ρ€Π΅ΡˆΠΈΠ»Π°ΡΡŒ, Ρ‚ΠΎ Π±ΡƒΠ΄Π΅Ρ‚
57 // ΠΈΠ·ΡŠΡΡ‚ ΠΈ освобоТдСн ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»ΡŒΠ½Ρ‹ΠΉ элСмСн, Ρ‡Ρ‚ΠΎ Π½Π΅ повлияСт Π½Π° Ρ…ΠΎΠ΄ всСго процСсса.
58 if (m_disposed && m_queue.TryDequeue(out instance))
59 Safe.Dispose(instance);
60
61 } else {
62 Safe.Dispose(instance);
63 }
64 }
65
66 protected virtual void Dispose(bool disposing) {
67 if (disposing) {
68 m_disposed = true;
69 T instance;
70 while (m_queue.TryDequeue(out instance))
71 Safe.Dispose(instance);
72 }
73 }
74
75 #region IDisposable implementation
76
77 public void Dispose() {
78 Dispose(true);
79 GC.SuppressFinalize(this);
80 }
81
82 #endregion
83 }*/
84 }
85
@@ -0,0 +1,24
1 using System;
2
3 namespace Implab {
4 /*public struct SyncPoolWrapper<T> : IDisposable {
5 readonly T m_value;
6 readonly SyncPool<T> m_pool;
7
8 internal SyncPoolWrapper(T value, SyncPool<T> pool) {
9 m_value = value;
10 m_pool = pool;
11 }
12
13 public T Value {
14 get { return m_value; }
15 }
16
17 #region IDisposable implementation
18 public void Dispose() {
19 m_pool.Release(m_value);
20 }
21 #endregion
22 }*/
23 }
24
@@ -1,434 +1,434
1 using System;
1 using System;
2 using System.Reflection;
2 using System.Reflection;
3 using System.Threading;
3 using System.Threading;
4 using Implab.Parallels;
4 using Implab.Parallels;
5
5
6 #if MONO
6 #if MONO
7
7
8 using NUnit.Framework;
8 using NUnit.Framework;
9 using TestClassAttribute = NUnit.Framework.TestFixtureAttribute;
9 using TestClassAttribute = NUnit.Framework.TestFixtureAttribute;
10 using TestMethod = NUnit.Framework.TestAttribute;
10 using TestMethod = NUnit.Framework.TestAttribute;
11
11
12 #else
12 #else
13
13
14 using Microsoft.VisualStudio.TestTools.UnitTesting;
14 using Microsoft.VisualStudio.TestTools.UnitTesting;
15
15
16 #endif
16 #endif
17
17
18 namespace Implab.Test {
18 namespace Implab.Test {
19 [TestClass]
19 [TestClass]
20 public class AsyncTests {
20 public class AsyncTests {
21 [TestMethod]
21 [TestMethod]
22 public void ResolveTest() {
22 public void ResolveTest() {
23 int res = -1;
23 int res = -1;
24 var p = new Promise<int>();
24 var p = new Promise<int>();
25 p.Then(x => res = x);
25 p.Then(x => res = x);
26 p.Resolve(100);
26 p.Resolve(100);
27
27
28 Assert.AreEqual(100, res);
28 Assert.AreEqual(100, res);
29 }
29 }
30
30
31 [TestMethod]
31 [TestMethod]
32 public void RejectTest() {
32 public void RejectTest() {
33 int res = -1;
33 int res = -1;
34 Exception err = null;
34 Exception err = null;
35
35
36 var p = new Promise<int>();
36 var p = new Promise<int>();
37 p.Then(
37 p.Then(
38 x => res = x,
38 x => res = x,
39 e => {
39 e => {
40 err = e;
40 err = e;
41 return -2;
41 return -2;
42 }
42 }
43 );
43 );
44 p.Reject(new ApplicationException("error"));
44 p.Reject(new ApplicationException("error"));
45
45
46 Assert.AreEqual(res, -1);
46 Assert.AreEqual(res, -1);
47 Assert.AreEqual(err.Message, "error");
47 Assert.AreEqual(err.Message, "error");
48
48
49 }
49 }
50
50
51 [TestMethod]
51 [TestMethod]
52 public void CancelExceptionTest() {
52 public void CancelExceptionTest() {
53 var p = new Promise<bool>();
53 var p = new Promise<bool>();
54 p.Cancel();
54 p.Cancel();
55
55
56 var p2 = p.Cancelled(() => {
56 var p2 = p.Cancelled(() => {
57 throw new ApplicationException("CANCELLED");
57 throw new ApplicationException("CANCELLED");
58 });
58 });
59
59
60 try {
60 try {
61 p2.Join();
61 p2.Join();
62 Assert.Fail();
62 Assert.Fail();
63 } catch (ApplicationException err) {
63 } catch (ApplicationException err) {
64 Assert.AreEqual("CANCELLED", err.InnerException.Message);
64 Assert.AreEqual("CANCELLED", err.InnerException.Message);
65 }
65 }
66
66
67 }
67 }
68
68
69 [TestMethod]
69 [TestMethod]
70 public void ContinueOnCancelTest() {
70 public void ContinueOnCancelTest() {
71 var p = new Promise<bool>();
71 var p = new Promise<bool>();
72 p.Cancel();
72 p.Cancel();
73
73
74 var p2 = p
74 var p2 = p
75 .Cancelled(() => {
75 .Cancelled(() => {
76 throw new ApplicationException("CANCELLED");
76 throw new ApplicationException("CANCELLED");
77 })
77 })
78 .Error(e => true);
78 .Error(e => true);
79
79
80 Assert.AreEqual(true, p2.Join());
80 Assert.AreEqual(true, p2.Join());
81 }
81 }
82
82
83 [TestMethod]
83 [TestMethod]
84 public void JoinSuccessTest() {
84 public void JoinSuccessTest() {
85 var p = new Promise<int>();
85 var p = new Promise<int>();
86 p.Resolve(100);
86 p.Resolve(100);
87 Assert.AreEqual(p.Join(), 100);
87 Assert.AreEqual(p.Join(), 100);
88 }
88 }
89
89
90 [TestMethod]
90 [TestMethod]
91 public void JoinFailTest() {
91 public void JoinFailTest() {
92 var p = new Promise<int>();
92 var p = new Promise<int>();
93 p.Reject(new ApplicationException("failed"));
93 p.Reject(new ApplicationException("failed"));
94
94
95 try {
95 try {
96 p.Join();
96 p.Join();
97 throw new ApplicationException("WRONG!");
97 throw new ApplicationException("WRONG!");
98 } catch (TargetInvocationException err) {
98 } catch (TargetInvocationException err) {
99 Assert.AreEqual(err.InnerException.Message, "failed");
99 Assert.AreEqual(err.InnerException.Message, "failed");
100 } catch {
100 } catch {
101 Assert.Fail("Got wrong excaption");
101 Assert.Fail("Got wrong excaption");
102 }
102 }
103 }
103 }
104
104
105 [TestMethod]
105 [TestMethod]
106 public void MapTest() {
106 public void MapTest() {
107 var p = new Promise<int>();
107 var p = new Promise<int>();
108
108
109 var p2 = p.Then(x => x.ToString());
109 var p2 = p.Then(x => x.ToString());
110 p.Resolve(100);
110 p.Resolve(100);
111
111
112 Assert.AreEqual(p2.Join(), "100");
112 Assert.AreEqual(p2.Join(), "100");
113 }
113 }
114
114
115 [TestMethod]
115 [TestMethod]
116 public void FixErrorTest() {
116 public void FixErrorTest() {
117 var p = new Promise<int>();
117 var p = new Promise<int>();
118
118
119 var p2 = p.Error(e => 101);
119 var p2 = p.Error(e => 101);
120
120
121 p.Reject(new Exception());
121 p.Reject(new Exception());
122
122
123 Assert.AreEqual(p2.Join(), 101);
123 Assert.AreEqual(p2.Join(), 101);
124 }
124 }
125
125
126 [TestMethod]
126 [TestMethod]
127 public void ChainTest() {
127 public void ChainTest() {
128 var p1 = new Promise<int>();
128 var p1 = new Promise<int>();
129
129
130 var p3 = p1.Chain(x => {
130 var p3 = p1.Chain(x => {
131 var p2 = new Promise<string>();
131 var p2 = new Promise<string>();
132 p2.Resolve(x.ToString());
132 p2.Resolve(x.ToString());
133 return p2;
133 return p2;
134 });
134 });
135
135
136 p1.Resolve(100);
136 p1.Resolve(100);
137
137
138 Assert.AreEqual(p3.Join(), "100");
138 Assert.AreEqual(p3.Join(), "100");
139 }
139 }
140
140
141 [TestMethod]
141 [TestMethod]
142 public void PoolTest() {
142 public void PoolTest() {
143 var pid = Thread.CurrentThread.ManagedThreadId;
143 var pid = Thread.CurrentThread.ManagedThreadId;
144 var p = AsyncPool.Invoke(() => Thread.CurrentThread.ManagedThreadId);
144 var p = AsyncPool.Invoke(() => Thread.CurrentThread.ManagedThreadId);
145
145
146 Assert.AreNotEqual(pid, p.Join());
146 Assert.AreNotEqual(pid, p.Join());
147 }
147 }
148
148
149 [TestMethod]
149 [TestMethod]
150 public void WorkerPoolSizeTest() {
150 public void WorkerPoolSizeTest() {
151 var pool = new WorkerPool(5, 10, 0);
151 var pool = new WorkerPool(5, 10, 0);
152
152
153 Assert.AreEqual(5, pool.PoolSize);
153 Assert.AreEqual(5, pool.PoolSize);
154
154
155 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
155 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
156 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
156 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
157 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
157 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
158
158
159 Assert.AreEqual(5, pool.PoolSize);
159 Assert.AreEqual(5, pool.PoolSize);
160
160
161 for (int i = 0; i < 100; i++)
161 for (int i = 0; i < 100; i++)
162 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
162 pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
163 Thread.Sleep(200);
163 Thread.Sleep(200);
164 Assert.AreEqual(10, pool.PoolSize);
164 Assert.AreEqual(10, pool.PoolSize);
165
165
166 pool.Dispose();
166 pool.Dispose();
167 }
167 }
168
168
169 [TestMethod]
169 [TestMethod]
170 public void WorkerPoolCorrectTest() {
170 public void WorkerPoolCorrectTest() {
171 var pool = new WorkerPool(0,1000,100);
171 var pool = new WorkerPool(0,1000,100);
172
172
173 const int iterations = 1000;
173 const int iterations = 1000;
174 int pending = iterations;
174 int pending = iterations;
175 var stop = new ManualResetEvent(false);
175 var stop = new ManualResetEvent(false);
176
176
177 var count = 0;
177 var count = 0;
178 for (int i = 0; i < iterations; i++) {
178 for (int i = 0; i < iterations; i++) {
179 pool
179 pool
180 .Invoke(() => 1)
180 .Invoke(() => 1)
181 .Then(x => Interlocked.Add(ref count, x))
181 .Then(x => Interlocked.Add(ref count, x))
182 .Then(x => Math.Log10(x))
182 .Then(x => Math.Log10(x))
183 .Anyway(() => {
183 .Anyway(() => {
184 Interlocked.Decrement(ref pending);
184 Interlocked.Decrement(ref pending);
185 if (pending == 0)
185 if (pending == 0)
186 stop.Set();
186 stop.Set();
187 });
187 });
188 }
188 }
189
189
190 stop.WaitOne();
190 stop.WaitOne();
191
191
192 Assert.AreEqual(iterations, count);
192 Assert.AreEqual(iterations, count);
193 Console.WriteLine("Max threads: {0}", pool.MaxRunningThreads);
193 Console.WriteLine("Max threads: {0}", pool.MaxRunningThreads);
194 pool.Dispose();
194 pool.Dispose();
195
195
196 }
196 }
197
197
198 [TestMethod]
198 [TestMethod]
199 public void WorkerPoolDisposeTest() {
199 public void WorkerPoolDisposeTest() {
200 var pool = new WorkerPool(5, 20);
200 var pool = new WorkerPool(5, 20);
201 Assert.AreEqual(5, pool.PoolSize);
201 Assert.AreEqual(5, pool.PoolSize);
202 pool.Dispose();
202 pool.Dispose();
203 Thread.Sleep(500);
203 Thread.Sleep(500);
204 Assert.AreEqual(0, pool.PoolSize);
204 Assert.AreEqual(0, pool.PoolSize);
205 pool.Dispose();
205 pool.Dispose();
206 }
206 }
207
207
208 [TestMethod]
208 [TestMethod]
209 public void MTQueueTest() {
209 public void MTQueueTest() {
210 var queue = new MTQueue<int>();
210 var queue = new MTQueue<int>();
211 int res;
211 int res;
212
212
213 queue.Enqueue(10);
213 queue.Enqueue(10);
214 Assert.IsTrue(queue.TryDequeue(out res));
214 Assert.IsTrue(queue.TryDequeue(out res));
215 Assert.AreEqual(10, res);
215 Assert.AreEqual(10, res);
216 Assert.IsFalse(queue.TryDequeue(out res));
216 Assert.IsFalse(queue.TryDequeue(out res));
217
217
218 for (int i = 0; i < 1000; i++)
218 for (int i = 0; i < 1000; i++)
219 queue.Enqueue(i);
219 queue.Enqueue(i);
220
220
221 for (int i = 0; i < 1000; i++) {
221 for (int i = 0; i < 1000; i++) {
222 queue.TryDequeue(out res);
222 queue.TryDequeue(out res);
223 Assert.AreEqual(i, res);
223 Assert.AreEqual(i, res);
224 }
224 }
225
225
226 int writers = 0;
226 int writers = 0;
227 int readers = 0;
227 int readers = 0;
228 var stop = new ManualResetEvent(false);
228 var stop = new ManualResetEvent(false);
229 int total = 0;
229 int total = 0;
230
230
231 const int itemsPerWriter = 10000;
231 const int itemsPerWriter = 10000;
232 const int writersCount = 10;
232 const int writersCount = 10;
233
233
234 for (int i = 0; i < writersCount; i++) {
234 for (int i = 0; i < writersCount; i++) {
235 Interlocked.Increment(ref writers);
235 Interlocked.Increment(ref writers);
236 AsyncPool
236 AsyncPool
237 .InvokeNewThread(() => {
237 .InvokeNewThread(() => {
238 for (int ii = 0; ii < itemsPerWriter; ii++) {
238 for (int ii = 0; ii < itemsPerWriter; ii++) {
239 queue.Enqueue(1);
239 queue.Enqueue(1);
240 }
240 }
241 return 1;
241 return 1;
242 })
242 })
243 .Anyway(() => Interlocked.Decrement(ref writers));
243 .Anyway(() => Interlocked.Decrement(ref writers));
244 }
244 }
245
245
246 for (int i = 0; i < 10; i++) {
246 for (int i = 0; i < 10; i++) {
247 Interlocked.Increment(ref readers);
247 Interlocked.Increment(ref readers);
248 AsyncPool
248 AsyncPool
249 .InvokeNewThread(() => {
249 .InvokeNewThread(() => {
250 int t;
250 int t;
251 do {
251 do {
252 while (queue.TryDequeue(out t))
252 while (queue.TryDequeue(out t))
253 Interlocked.Add(ref total, t);
253 Interlocked.Add(ref total, t);
254 } while (writers > 0);
254 } while (writers > 0);
255 return 1;
255 return 1;
256 })
256 })
257 .Anyway(() => {
257 .Anyway(() => {
258 Interlocked.Decrement(ref readers);
258 Interlocked.Decrement(ref readers);
259 if (readers == 0)
259 if (readers == 0)
260 stop.Set();
260 stop.Set();
261 });
261 });
262 }
262 }
263
263
264 stop.WaitOne();
264 stop.WaitOne();
265
265
266 Assert.AreEqual(itemsPerWriter * writersCount, total);
266 Assert.AreEqual(itemsPerWriter * writersCount, total);
267 }
267 }
268
268
269 [TestMethod]
269 [TestMethod]
270 public void ParallelMapTest() {
270 public void ParallelMapTest() {
271
271
272 const int count = 100000;
272 const int count = 100000;
273
273
274 var args = new double[count];
274 var args = new double[count];
275 var rand = new Random();
275 var rand = new Random();
276
276
277 for (int i = 0; i < count; i++)
277 for (int i = 0; i < count; i++)
278 args[i] = rand.NextDouble();
278 args[i] = rand.NextDouble();
279
279
280 var t = Environment.TickCount;
280 var t = Environment.TickCount;
281 var res = args.ParallelMap(x => Math.Sin(x*x), 4).Join();
281 var res = args.ParallelMap(x => Math.Sin(x*x), 4).Join();
282
282
283 Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t);
283 Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t);
284
284
285 t = Environment.TickCount;
285 t = Environment.TickCount;
286 for (int i = 0; i < count; i++)
286 for (int i = 0; i < count; i++)
287 Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]);
287 Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]);
288 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
288 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
289 }
289 }
290
290
291 [TestMethod]
291 [TestMethod]
292 public void ChainedMapTest() {
292 public void ChainedMapTest() {
293
293
294 using (var pool = new WorkerPool(0,100,100)) {
294 using (var pool = new WorkerPool(0,10,100)) {
295 const int count = 10000;
295 const int count = 10000;
296
296
297 var args = new double[count];
297 var args = new double[count];
298 var rand = new Random();
298 var rand = new Random();
299
299
300 for (int i = 0; i < count; i++)
300 for (int i = 0; i < count; i++)
301 args[i] = rand.NextDouble();
301 args[i] = rand.NextDouble();
302
302
303 var t = Environment.TickCount;
303 var t = Environment.TickCount;
304 var res = args
304 var res = args
305 .ChainedMap(
305 .ChainedMap(
306 // Analysis disable once AccessToDisposedClosure
306 // Analysis disable once AccessToDisposedClosure
307 x => pool.Invoke(
307 x => pool.Invoke(
308 () => Math.Sin(x * x)
308 () => Math.Sin(x * x)
309 ),
309 ),
310 4
310 4
311 )
311 )
312 .Join();
312 .Join();
313
313
314 Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t);
314 Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t);
315
315
316 t = Environment.TickCount;
316 t = Environment.TickCount;
317 for (int i = 0; i < count; i++)
317 for (int i = 0; i < count; i++)
318 Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]);
318 Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]);
319 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
319 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
320 Console.WriteLine("Max workers: {0}", pool.MaxRunningThreads);
320 Console.WriteLine("Max workers: {0}", pool.MaxRunningThreads);
321 }
321 }
322 }
322 }
323
323
324 [TestMethod]
324 [TestMethod]
325 public void ParallelForEachTest() {
325 public void ParallelForEachTest() {
326
326
327 const int count = 100000;
327 const int count = 100000;
328
328
329 var args = new int[count];
329 var args = new int[count];
330 var rand = new Random();
330 var rand = new Random();
331
331
332 for (int i = 0; i < count; i++)
332 for (int i = 0; i < count; i++)
333 args[i] = (int)(rand.NextDouble() * 100);
333 args[i] = (int)(rand.NextDouble() * 100);
334
334
335 int result = 0;
335 int result = 0;
336
336
337 var t = Environment.TickCount;
337 var t = Environment.TickCount;
338 args.ParallelForEach(x => Interlocked.Add(ref result, x), 4).Join();
338 args.ParallelForEach(x => Interlocked.Add(ref result, x), 4).Join();
339
339
340 Console.WriteLine("Iteration complete in {0} ms, result: {1}", Environment.TickCount - t, result);
340 Console.WriteLine("Iteration complete in {0} ms, result: {1}", Environment.TickCount - t, result);
341
341
342 int result2 = 0;
342 int result2 = 0;
343
343
344 t = Environment.TickCount;
344 t = Environment.TickCount;
345 for (int i = 0; i < count; i++)
345 for (int i = 0; i < count; i++)
346 result2 += args[i];
346 result2 += args[i];
347 Assert.AreEqual(result2, result);
347 Assert.AreEqual(result2, result);
348 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
348 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
349 }
349 }
350
350
351 [TestMethod]
351 [TestMethod]
352 public void ComplexCase1Test() {
352 public void ComplexCase1Test() {
353 var flags = new bool[3];
353 var flags = new bool[3];
354
354
355 // op1 (aync 200ms) => op2 (async 200ms) => op3 (sync map)
355 // op1 (aync 200ms) => op2 (async 200ms) => op3 (sync map)
356
356
357 var step1 = PromiseHelper
357 var step1 = PromiseHelper
358 .Sleep(200, "Alan")
358 .Sleep(200, "Alan")
359 .Cancelled(() => flags[0] = true);
359 .Cancelled(() => flags[0] = true);
360 var p = step1
360 var p = step1
361 .Chain(x =>
361 .Chain(x =>
362 PromiseHelper
362 PromiseHelper
363 .Sleep(200, "Hi, " + x)
363 .Sleep(200, "Hi, " + x)
364 .Then(y => y)
364 .Then(y => y)
365 .Cancelled(() => flags[1] = true)
365 .Cancelled(() => flags[1] = true)
366 )
366 )
367 .Cancelled(() => flags[2] = true);
367 .Cancelled(() => flags[2] = true);
368 step1.Join();
368 step1.Join();
369 p.Cancel();
369 p.Cancel();
370 try {
370 try {
371 Assert.AreEqual(p.Join(), "Hi, Alan");
371 Assert.AreEqual(p.Join(), "Hi, Alan");
372 Assert.Fail("Shouldn't get here");
372 Assert.Fail("Shouldn't get here");
373 } catch (OperationCanceledException) {
373 } catch (OperationCanceledException) {
374 }
374 }
375
375
376 Assert.IsFalse(flags[0]);
376 Assert.IsFalse(flags[0]);
377 Assert.IsTrue(flags[1]);
377 Assert.IsTrue(flags[1]);
378 Assert.IsTrue(flags[2]);
378 Assert.IsTrue(flags[2]);
379 }
379 }
380
380
381 [TestMethod]
381 [TestMethod]
382 public void ChainedCancel1Test() {
382 public void ChainedCancel1Test() {
383 // ΠΏΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ сцСплСнной асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ всС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ
383 // ΠΏΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ сцСплСнной асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ всС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ
384 // Π·Π°Π²Π΅Ρ€ΡˆΠ°Ρ‚ΡŒΡΡ ошибкой OperationCanceledException
384 // Π·Π°Π²Π΅Ρ€ΡˆΠ°Ρ‚ΡŒΡΡ ошибкой OperationCanceledException
385 var p = PromiseHelper
385 var p = PromiseHelper
386 .Sleep(1, "Hi, HAL!")
386 .Sleep(1, "Hi, HAL!")
387 .Then(x => {
387 .Then(x => {
388 // запускаСм Π΄Π²Π΅ асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ
388 // запускаСм Π΄Π²Π΅ асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ
389 var result = PromiseHelper.Sleep(1000, "HEM ENABLED!!!");
389 var result = PromiseHelper.Sleep(1000, "HEM ENABLED!!!");
390 // вторая опСрация отмСняСт ΠΏΠ΅Ρ€Π²ΡƒΡŽ Π΄ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ
390 // вторая опСрация отмСняСт ΠΏΠ΅Ρ€Π²ΡƒΡŽ Π΄ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ
391 PromiseHelper
391 PromiseHelper
392 .Sleep(100, "HAL, STOP!")
392 .Sleep(100, "HAL, STOP!")
393 .Then(result.Cancel);
393 .Then(result.Cancel);
394 return result;
394 return result;
395 });
395 });
396 try {
396 try {
397 p.Join();
397 p.Join();
398 } catch (TargetInvocationException err) {
398 } catch (TargetInvocationException err) {
399 Assert.IsTrue(err.InnerException is OperationCanceledException);
399 Assert.IsTrue(err.InnerException is OperationCanceledException);
400 }
400 }
401 }
401 }
402
402
403 [TestMethod]
403 [TestMethod]
404 public void ChainedCancel2Test() {
404 public void ChainedCancel2Test() {
405 // ΠΏΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ, Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Ρ‚Π°ΠΊΠΆΠ΅ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΎΡ‚ΠΌΠ΅Π½ΡΡ‚ΡŒΡΡ
405 // ΠΏΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ, Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Ρ‚Π°ΠΊΠΆΠ΅ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΎΡ‚ΠΌΠ΅Π½ΡΡ‚ΡŒΡΡ
406 var pSurvive = new Promise<bool>();
406 var pSurvive = new Promise<bool>();
407 var hemStarted = new ManualResetEvent(false);
407 var hemStarted = new ManualResetEvent(false);
408 var p = PromiseHelper
408 var p = PromiseHelper
409 .Sleep(1, "Hi, HAL!")
409 .Sleep(1, "Hi, HAL!")
410 .Chain(x => {
410 .Chain(x => {
411 hemStarted.Set();
411 hemStarted.Set();
412 // запускаСм Π΄Π²Π΅ асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ
412 // запускаСм Π΄Π²Π΅ асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ
413 var result = PromiseHelper
413 var result = PromiseHelper
414 .Sleep(10000, "HEM ENABLED!!!")
414 .Sleep(10000, "HEM ENABLED!!!")
415 .Then(s => pSurvive.Resolve(false));
415 .Then(s => pSurvive.Resolve(false));
416
416
417 result
417 result
418 .Cancelled(() => pSurvive.Resolve(true));
418 .Cancelled(() => pSurvive.Resolve(true));
419
419
420 return result;
420 return result;
421 });
421 });
422
422
423 hemStarted.WaitOne();
423 hemStarted.WaitOne();
424 p.Cancel();
424 p.Cancel();
425
425
426 try {
426 try {
427 p.Join();
427 p.Join();
428 } catch (OperationCanceledException) {
428 } catch (OperationCanceledException) {
429 Assert.IsTrue(pSurvive.Join());
429 Assert.IsTrue(pSurvive.Join());
430 }
430 }
431 }
431 }
432 }
432 }
433 }
433 }
434
434
@@ -1,290 +1,287
1 ο»Ώ
1 ο»Ώ
2 Microsoft Visual Studio Solution File, Format Version 11.00
2 Microsoft Visual Studio Solution File, Format Version 11.00
3 # Visual Studio 2010
3 # Visual Studio 2010
4 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab", "Implab\Implab.csproj", "{F550F1F8-8746-4AD0-9614-855F4C4B7F05}"
4 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab", "Implab\Implab.csproj", "{F550F1F8-8746-4AD0-9614-855F4C4B7F05}"
5 EndProject
5 EndProject
6 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{CE8D8D18-437A-445C-B662-4C2CE79A76F6}"
6 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{CE8D8D18-437A-445C-B662-4C2CE79A76F6}"
7 ProjectSection(SolutionItems) = preProject
7 ProjectSection(SolutionItems) = preProject
8 Implab.vsmdi = Implab.vsmdi
8 Implab.vsmdi = Implab.vsmdi
9 Local.testsettings = Local.testsettings
9 Local.testsettings = Local.testsettings
10 TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings
10 TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings
11 EndProjectSection
11 EndProjectSection
12 EndProject
12 EndProject
13 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Fx", "Implab.Fx\Implab.Fx.csproj", "{06E706F8-6881-43EB-927E-FFC503AF6ABC}"
13 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Fx", "Implab.Fx\Implab.Fx.csproj", "{06E706F8-6881-43EB-927E-FFC503AF6ABC}"
14 EndProject
14 EndProject
15 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{BCA337C3-BFDC-4825-BBDB-E6D467E4E452}"
15 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{BCA337C3-BFDC-4825-BBDB-E6D467E4E452}"
16 EndProject
16 EndProject
17 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Test.mono", "Implab.Test\Implab.Test.mono.csproj", "{2BD05F84-E067-4B87-9477-FDC2676A21C6}"
17 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Test.mono", "Implab.Test\Implab.Test.mono.csproj", "{2BD05F84-E067-4B87-9477-FDC2676A21C6}"
18 EndProject
18 EndProject
19 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Fx.Test.mono", "Implab.Fx.Test\Implab.Fx.Test.mono.csproj", "{2BD05F84-E067-4B87-9477-FDC2676A21C6}"
20 EndProject
21 Global
19 Global
22 GlobalSection(SolutionConfigurationPlatforms) = preSolution
20 GlobalSection(SolutionConfigurationPlatforms) = preSolution
23 Debug|Any CPU = Debug|Any CPU
21 Debug|Any CPU = Debug|Any CPU
24 Release|Any CPU = Release|Any CPU
22 Release|Any CPU = Release|Any CPU
25 Debug 4.5|Any CPU = Debug 4.5|Any CPU
23 Debug 4.5|Any CPU = Debug 4.5|Any CPU
26 Release 4.5|Any CPU = Release 4.5|Any CPU
24 Release 4.5|Any CPU = Release 4.5|Any CPU
27 EndGlobalSection
25 EndGlobalSection
28 GlobalSection(ProjectConfigurationPlatforms) = postSolution
26 GlobalSection(ProjectConfigurationPlatforms) = postSolution
29 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
27 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
30 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
28 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
31 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
32 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug|Any CPU.Build.0 = Debug|Any CPU
33 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
31 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
34 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
32 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
35 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release|Any CPU.ActiveCfg = Release|Any CPU
36 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release|Any CPU.Build.0 = Release|Any CPU
34 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release|Any CPU.Build.0 = Release|Any CPU
37 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
35 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
38 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
36 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
39 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
37 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
40 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
38 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
41 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
42 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
40 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
41 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
44 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
42 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
45 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
43 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
46 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
44 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
47 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
45 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
48 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
46 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
49 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
47 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
50 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
48 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
51 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release|Any CPU.Build.0 = Release|Any CPU
49 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release|Any CPU.Build.0 = Release|Any CPU
52 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release|Any CPU.Build.0 = Release|Any CPU
50 {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release|Any CPU.Build.0 = Release|Any CPU
53 {2F31E405-E267-4195-A05D-574093C21209}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
51 {2F31E405-E267-4195-A05D-574093C21209}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
54 {2F31E405-E267-4195-A05D-574093C21209}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
52 {2F31E405-E267-4195-A05D-574093C21209}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
55 {2F31E405-E267-4195-A05D-574093C21209}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
53 {2F31E405-E267-4195-A05D-574093C21209}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
56 {2F31E405-E267-4195-A05D-574093C21209}.Debug|Any CPU.Build.0 = Debug|Any CPU
54 {2F31E405-E267-4195-A05D-574093C21209}.Debug|Any CPU.Build.0 = Debug|Any CPU
57 {2F31E405-E267-4195-A05D-574093C21209}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
55 {2F31E405-E267-4195-A05D-574093C21209}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
58 {2F31E405-E267-4195-A05D-574093C21209}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
56 {2F31E405-E267-4195-A05D-574093C21209}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
59 {2F31E405-E267-4195-A05D-574093C21209}.Release|Any CPU.ActiveCfg = Release|Any CPU
57 {2F31E405-E267-4195-A05D-574093C21209}.Release|Any CPU.ActiveCfg = Release|Any CPU
60 {2F31E405-E267-4195-A05D-574093C21209}.Release|Any CPU.Build.0 = Release|Any CPU
58 {2F31E405-E267-4195-A05D-574093C21209}.Release|Any CPU.Build.0 = Release|Any CPU
61 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
59 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
62 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
60 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
63 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
61 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
64 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
62 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
65 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
63 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
66 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
64 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
67 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
65 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
68 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release|Any CPU.Build.0 = Release|Any CPU
66 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release|Any CPU.Build.0 = Release|Any CPU
69 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
67 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
70 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
68 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
71 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
69 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
72 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug|Any CPU.Build.0 = Debug|Any CPU
70 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug|Any CPU.Build.0 = Debug|Any CPU
73 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
71 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
74 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
72 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
75 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release|Any CPU.ActiveCfg = Release|Any CPU
73 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release|Any CPU.ActiveCfg = Release|Any CPU
76 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release|Any CPU.Build.0 = Release|Any CPU
74 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release|Any CPU.Build.0 = Release|Any CPU
77 EndGlobalSection
75 EndGlobalSection
78 GlobalSection(NestedProjects) = preSolution
76 GlobalSection(NestedProjects) = preSolution
79 {2BD05F84-E067-4B87-9477-FDC2676A21C6} = {BCA337C3-BFDC-4825-BBDB-E6D467E4E452}
77 {2BD05F84-E067-4B87-9477-FDC2676A21C6} = {BCA337C3-BFDC-4825-BBDB-E6D467E4E452}
80 {2BD05F84-E067-4B87-9477-FDC2676A21C6} = {BCA337C3-BFDC-4825-BBDB-E6D467E4E452}
81 EndGlobalSection
78 EndGlobalSection
82 GlobalSection(MonoDevelopProperties) = preSolution
79 GlobalSection(MonoDevelopProperties) = preSolution
83 StartupItem = Implab\Implab.csproj
80 StartupItem = Implab\Implab.csproj
84 Policies = $0
81 Policies = $0
85 $0.CSharpFormattingPolicy = $1
82 $0.CSharpFormattingPolicy = $1
86 $1.IndentSwitchBody = True
83 $1.IndentSwitchBody = True
87 $1.NamespaceBraceStyle = EndOfLine
84 $1.NamespaceBraceStyle = EndOfLine
88 $1.ClassBraceStyle = EndOfLine
85 $1.ClassBraceStyle = EndOfLine
89 $1.InterfaceBraceStyle = EndOfLine
86 $1.InterfaceBraceStyle = EndOfLine
90 $1.StructBraceStyle = EndOfLine
87 $1.StructBraceStyle = EndOfLine
91 $1.EnumBraceStyle = EndOfLine
88 $1.EnumBraceStyle = EndOfLine
92 $1.MethodBraceStyle = EndOfLine
89 $1.MethodBraceStyle = EndOfLine
93 $1.ConstructorBraceStyle = EndOfLine
90 $1.ConstructorBraceStyle = EndOfLine
94 $1.DestructorBraceStyle = EndOfLine
91 $1.DestructorBraceStyle = EndOfLine
95 $1.BeforeMethodDeclarationParentheses = False
92 $1.BeforeMethodDeclarationParentheses = False
96 $1.BeforeMethodCallParentheses = False
93 $1.BeforeMethodCallParentheses = False
97 $1.BeforeConstructorDeclarationParentheses = False
94 $1.BeforeConstructorDeclarationParentheses = False
98 $1.NewLineBeforeConstructorInitializerColon = NewLine
95 $1.NewLineBeforeConstructorInitializerColon = NewLine
99 $1.NewLineAfterConstructorInitializerColon = SameLine
96 $1.NewLineAfterConstructorInitializerColon = SameLine
100 $1.BeforeIndexerDeclarationBracket = False
97 $1.BeforeIndexerDeclarationBracket = False
101 $1.BeforeDelegateDeclarationParentheses = False
98 $1.BeforeDelegateDeclarationParentheses = False
102 $1.NewParentheses = False
99 $1.NewParentheses = False
103 $1.SpacesBeforeBrackets = False
100 $1.SpacesBeforeBrackets = False
104 $1.inheritsSet = Mono
101 $1.inheritsSet = Mono
105 $1.inheritsScope = text/x-csharp
102 $1.inheritsScope = text/x-csharp
106 $1.scope = text/x-csharp
103 $1.scope = text/x-csharp
107 $0.TextStylePolicy = $2
104 $0.TextStylePolicy = $2
108 $2.FileWidth = 120
105 $2.FileWidth = 120
109 $2.EolMarker = Unix
106 $2.EolMarker = Unix
110 $2.inheritsSet = VisualStudio
107 $2.inheritsSet = VisualStudio
111 $2.inheritsScope = text/plain
108 $2.inheritsScope = text/plain
112 $2.scope = text/x-csharp
109 $2.scope = text/x-csharp
113 $0.DotNetNamingPolicy = $3
110 $0.DotNetNamingPolicy = $3
114 $3.DirectoryNamespaceAssociation = PrefixedHierarchical
111 $3.DirectoryNamespaceAssociation = PrefixedHierarchical
115 $3.ResourceNamePolicy = MSBuild
112 $3.ResourceNamePolicy = MSBuild
116 $0.TextStylePolicy = $4
113 $0.TextStylePolicy = $4
117 $4.FileWidth = 120
114 $4.FileWidth = 120
118 $4.TabsToSpaces = False
115 $4.TabsToSpaces = False
119 $4.inheritsSet = VisualStudio
116 $4.inheritsSet = VisualStudio
120 $4.inheritsScope = text/plain
117 $4.inheritsScope = text/plain
121 $4.scope = application/xml
118 $4.scope = application/xml
122 $0.XmlFormattingPolicy = $5
119 $0.XmlFormattingPolicy = $5
123 $5.inheritsSet = Mono
120 $5.inheritsSet = Mono
124 $5.inheritsScope = application/xml
121 $5.inheritsScope = application/xml
125 $5.scope = application/xml
122 $5.scope = application/xml
126 $0.TextStylePolicy = $6
123 $0.TextStylePolicy = $6
127 $6.FileWidth = 120
124 $6.FileWidth = 120
128 $6.TabsToSpaces = False
125 $6.TabsToSpaces = False
129 $6.inheritsSet = VisualStudio
126 $6.inheritsSet = VisualStudio
130 $6.inheritsScope = text/plain
127 $6.inheritsScope = text/plain
131 $6.scope = text/plain
128 $6.scope = text/plain
132 $0.NameConventionPolicy = $7
129 $0.NameConventionPolicy = $7
133 $7.Rules = $8
130 $7.Rules = $8
134 $8.NamingRule = $9
131 $8.NamingRule = $9
135 $9.Name = Namespaces
132 $9.Name = Namespaces
136 $9.AffectedEntity = Namespace
133 $9.AffectedEntity = Namespace
137 $9.VisibilityMask = VisibilityMask
134 $9.VisibilityMask = VisibilityMask
138 $9.NamingStyle = PascalCase
135 $9.NamingStyle = PascalCase
139 $9.IncludeInstanceMembers = True
136 $9.IncludeInstanceMembers = True
140 $9.IncludeStaticEntities = True
137 $9.IncludeStaticEntities = True
141 $8.NamingRule = $10
138 $8.NamingRule = $10
142 $10.Name = Types
139 $10.Name = Types
143 $10.AffectedEntity = Class, Struct, Enum, Delegate
140 $10.AffectedEntity = Class, Struct, Enum, Delegate
144 $10.VisibilityMask = VisibilityMask
141 $10.VisibilityMask = VisibilityMask
145 $10.NamingStyle = PascalCase
142 $10.NamingStyle = PascalCase
146 $10.IncludeInstanceMembers = True
143 $10.IncludeInstanceMembers = True
147 $10.IncludeStaticEntities = True
144 $10.IncludeStaticEntities = True
148 $8.NamingRule = $11
145 $8.NamingRule = $11
149 $11.Name = Interfaces
146 $11.Name = Interfaces
150 $11.RequiredPrefixes = $12
147 $11.RequiredPrefixes = $12
151 $12.String = I
148 $12.String = I
152 $11.AffectedEntity = Interface
149 $11.AffectedEntity = Interface
153 $11.VisibilityMask = VisibilityMask
150 $11.VisibilityMask = VisibilityMask
154 $11.NamingStyle = PascalCase
151 $11.NamingStyle = PascalCase
155 $11.IncludeInstanceMembers = True
152 $11.IncludeInstanceMembers = True
156 $11.IncludeStaticEntities = True
153 $11.IncludeStaticEntities = True
157 $8.NamingRule = $13
154 $8.NamingRule = $13
158 $13.Name = Attributes
155 $13.Name = Attributes
159 $13.RequiredSuffixes = $14
156 $13.RequiredSuffixes = $14
160 $14.String = Attribute
157 $14.String = Attribute
161 $13.AffectedEntity = CustomAttributes
158 $13.AffectedEntity = CustomAttributes
162 $13.VisibilityMask = VisibilityMask
159 $13.VisibilityMask = VisibilityMask
163 $13.NamingStyle = PascalCase
160 $13.NamingStyle = PascalCase
164 $13.IncludeInstanceMembers = True
161 $13.IncludeInstanceMembers = True
165 $13.IncludeStaticEntities = True
162 $13.IncludeStaticEntities = True
166 $8.NamingRule = $15
163 $8.NamingRule = $15
167 $15.Name = Event Arguments
164 $15.Name = Event Arguments
168 $15.RequiredSuffixes = $16
165 $15.RequiredSuffixes = $16
169 $16.String = EventArgs
166 $16.String = EventArgs
170 $15.AffectedEntity = CustomEventArgs
167 $15.AffectedEntity = CustomEventArgs
171 $15.VisibilityMask = VisibilityMask
168 $15.VisibilityMask = VisibilityMask
172 $15.NamingStyle = PascalCase
169 $15.NamingStyle = PascalCase
173 $15.IncludeInstanceMembers = True
170 $15.IncludeInstanceMembers = True
174 $15.IncludeStaticEntities = True
171 $15.IncludeStaticEntities = True
175 $8.NamingRule = $17
172 $8.NamingRule = $17
176 $17.Name = Exceptions
173 $17.Name = Exceptions
177 $17.RequiredSuffixes = $18
174 $17.RequiredSuffixes = $18
178 $18.String = Exception
175 $18.String = Exception
179 $17.AffectedEntity = CustomExceptions
176 $17.AffectedEntity = CustomExceptions
180 $17.VisibilityMask = VisibilityMask
177 $17.VisibilityMask = VisibilityMask
181 $17.NamingStyle = PascalCase
178 $17.NamingStyle = PascalCase
182 $17.IncludeInstanceMembers = True
179 $17.IncludeInstanceMembers = True
183 $17.IncludeStaticEntities = True
180 $17.IncludeStaticEntities = True
184 $8.NamingRule = $19
181 $8.NamingRule = $19
185 $19.Name = Methods
182 $19.Name = Methods
186 $19.AffectedEntity = Methods
183 $19.AffectedEntity = Methods
187 $19.VisibilityMask = VisibilityMask
184 $19.VisibilityMask = VisibilityMask
188 $19.NamingStyle = PascalCase
185 $19.NamingStyle = PascalCase
189 $19.IncludeInstanceMembers = True
186 $19.IncludeInstanceMembers = True
190 $19.IncludeStaticEntities = True
187 $19.IncludeStaticEntities = True
191 $8.NamingRule = $20
188 $8.NamingRule = $20
192 $20.Name = Static Readonly Fields
189 $20.Name = Static Readonly Fields
193 $20.AffectedEntity = ReadonlyField
190 $20.AffectedEntity = ReadonlyField
194 $20.VisibilityMask = Internal, Protected, Public
191 $20.VisibilityMask = Internal, Protected, Public
195 $20.NamingStyle = PascalCase
192 $20.NamingStyle = PascalCase
196 $20.IncludeInstanceMembers = False
193 $20.IncludeInstanceMembers = False
197 $20.IncludeStaticEntities = True
194 $20.IncludeStaticEntities = True
198 $8.NamingRule = $21
195 $8.NamingRule = $21
199 $21.Name = Fields (Non Private)
196 $21.Name = Fields (Non Private)
200 $21.AffectedEntity = Field
197 $21.AffectedEntity = Field
201 $21.VisibilityMask = Internal, Public
198 $21.VisibilityMask = Internal, Public
202 $21.NamingStyle = CamelCase
199 $21.NamingStyle = CamelCase
203 $21.IncludeInstanceMembers = True
200 $21.IncludeInstanceMembers = True
204 $21.IncludeStaticEntities = True
201 $21.IncludeStaticEntities = True
205 $8.NamingRule = $22
202 $8.NamingRule = $22
206 $22.Name = ReadOnly Fields (Non Private)
203 $22.Name = ReadOnly Fields (Non Private)
207 $22.AffectedEntity = ReadonlyField
204 $22.AffectedEntity = ReadonlyField
208 $22.VisibilityMask = Internal, Public
205 $22.VisibilityMask = Internal, Public
209 $22.NamingStyle = CamelCase
206 $22.NamingStyle = CamelCase
210 $22.IncludeInstanceMembers = True
207 $22.IncludeInstanceMembers = True
211 $22.IncludeStaticEntities = False
208 $22.IncludeStaticEntities = False
212 $8.NamingRule = $23
209 $8.NamingRule = $23
213 $23.Name = Fields (Private)
210 $23.Name = Fields (Private)
214 $23.RequiredPrefixes = $24
211 $23.RequiredPrefixes = $24
215 $24.String = m_
212 $24.String = m_
216 $23.AffectedEntity = Field, ReadonlyField
213 $23.AffectedEntity = Field, ReadonlyField
217 $23.VisibilityMask = Private, Protected
214 $23.VisibilityMask = Private, Protected
218 $23.NamingStyle = CamelCase
215 $23.NamingStyle = CamelCase
219 $23.IncludeInstanceMembers = True
216 $23.IncludeInstanceMembers = True
220 $23.IncludeStaticEntities = False
217 $23.IncludeStaticEntities = False
221 $8.NamingRule = $25
218 $8.NamingRule = $25
222 $25.Name = Static Fields (Private)
219 $25.Name = Static Fields (Private)
223 $25.RequiredPrefixes = $26
220 $25.RequiredPrefixes = $26
224 $26.String = _
221 $26.String = _
225 $25.AffectedEntity = Field
222 $25.AffectedEntity = Field
226 $25.VisibilityMask = Private
223 $25.VisibilityMask = Private
227 $25.NamingStyle = CamelCase
224 $25.NamingStyle = CamelCase
228 $25.IncludeInstanceMembers = False
225 $25.IncludeInstanceMembers = False
229 $25.IncludeStaticEntities = True
226 $25.IncludeStaticEntities = True
230 $8.NamingRule = $27
227 $8.NamingRule = $27
231 $27.Name = ReadOnly Fields (Private)
228 $27.Name = ReadOnly Fields (Private)
232 $27.RequiredPrefixes = $28
229 $27.RequiredPrefixes = $28
233 $28.String = m_
230 $28.String = m_
234 $27.AffectedEntity = ReadonlyField
231 $27.AffectedEntity = ReadonlyField
235 $27.VisibilityMask = Private, Protected
232 $27.VisibilityMask = Private, Protected
236 $27.NamingStyle = CamelCase
233 $27.NamingStyle = CamelCase
237 $27.IncludeInstanceMembers = True
234 $27.IncludeInstanceMembers = True
238 $27.IncludeStaticEntities = False
235 $27.IncludeStaticEntities = False
239 $8.NamingRule = $29
236 $8.NamingRule = $29
240 $29.Name = Constant Fields
237 $29.Name = Constant Fields
241 $29.AffectedEntity = ConstantField
238 $29.AffectedEntity = ConstantField
242 $29.VisibilityMask = VisibilityMask
239 $29.VisibilityMask = VisibilityMask
243 $29.NamingStyle = AllUpper
240 $29.NamingStyle = AllUpper
244 $29.IncludeInstanceMembers = True
241 $29.IncludeInstanceMembers = True
245 $29.IncludeStaticEntities = True
242 $29.IncludeStaticEntities = True
246 $8.NamingRule = $30
243 $8.NamingRule = $30
247 $30.Name = Properties
244 $30.Name = Properties
248 $30.AffectedEntity = Property
245 $30.AffectedEntity = Property
249 $30.VisibilityMask = VisibilityMask
246 $30.VisibilityMask = VisibilityMask
250 $30.NamingStyle = PascalCase
247 $30.NamingStyle = PascalCase
251 $30.IncludeInstanceMembers = True
248 $30.IncludeInstanceMembers = True
252 $30.IncludeStaticEntities = True
249 $30.IncludeStaticEntities = True
253 $8.NamingRule = $31
250 $8.NamingRule = $31
254 $31.Name = Events
251 $31.Name = Events
255 $31.AffectedEntity = Event
252 $31.AffectedEntity = Event
256 $31.VisibilityMask = VisibilityMask
253 $31.VisibilityMask = VisibilityMask
257 $31.NamingStyle = PascalCase
254 $31.NamingStyle = PascalCase
258 $31.IncludeInstanceMembers = True
255 $31.IncludeInstanceMembers = True
259 $31.IncludeStaticEntities = True
256 $31.IncludeStaticEntities = True
260 $8.NamingRule = $32
257 $8.NamingRule = $32
261 $32.Name = Enum Members
258 $32.Name = Enum Members
262 $32.AffectedEntity = EnumMember
259 $32.AffectedEntity = EnumMember
263 $32.VisibilityMask = VisibilityMask
260 $32.VisibilityMask = VisibilityMask
264 $32.NamingStyle = PascalCase
261 $32.NamingStyle = PascalCase
265 $32.IncludeInstanceMembers = True
262 $32.IncludeInstanceMembers = True
266 $32.IncludeStaticEntities = True
263 $32.IncludeStaticEntities = True
267 $8.NamingRule = $33
264 $8.NamingRule = $33
268 $33.Name = Parameters
265 $33.Name = Parameters
269 $33.AffectedEntity = Parameter, LocalVariable
266 $33.AffectedEntity = Parameter, LocalVariable
270 $33.VisibilityMask = VisibilityMask
267 $33.VisibilityMask = VisibilityMask
271 $33.NamingStyle = CamelCase
268 $33.NamingStyle = CamelCase
272 $33.IncludeInstanceMembers = True
269 $33.IncludeInstanceMembers = True
273 $33.IncludeStaticEntities = True
270 $33.IncludeStaticEntities = True
274 $8.NamingRule = $34
271 $8.NamingRule = $34
275 $34.Name = Type Parameters
272 $34.Name = Type Parameters
276 $34.RequiredPrefixes = $35
273 $34.RequiredPrefixes = $35
277 $35.String = T
274 $35.String = T
278 $34.AffectedEntity = TypeParameter
275 $34.AffectedEntity = TypeParameter
279 $34.VisibilityMask = VisibilityMask
276 $34.VisibilityMask = VisibilityMask
280 $34.NamingStyle = PascalCase
277 $34.NamingStyle = PascalCase
281 $34.IncludeInstanceMembers = True
278 $34.IncludeInstanceMembers = True
282 $34.IncludeStaticEntities = True
279 $34.IncludeStaticEntities = True
283 EndGlobalSection
280 EndGlobalSection
284 GlobalSection(TestCaseManagementSettings) = postSolution
281 GlobalSection(TestCaseManagementSettings) = postSolution
285 CategoryFile = Implab.vsmdi
282 CategoryFile = Implab.vsmdi
286 EndGlobalSection
283 EndGlobalSection
287 GlobalSection(SolutionProperties) = preSolution
284 GlobalSection(SolutionProperties) = preSolution
288 HideSolutionNode = FALSE
285 HideSolutionNode = FALSE
289 EndGlobalSection
286 EndGlobalSection
290 EndGlobal
287 EndGlobal
@@ -1,196 +1,200
1 ο»Ώ<?xml version="1.0" encoding="utf-8"?>
1 ο»Ώ<?xml version="1.0" encoding="utf-8"?>
2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <PropertyGroup>
3 <PropertyGroup>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6 <ProjectGuid>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</ProjectGuid>
6 <ProjectGuid>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</ProjectGuid>
7 <OutputType>Library</OutputType>
7 <OutputType>Library</OutputType>
8 <RootNamespace>Implab</RootNamespace>
8 <RootNamespace>Implab</RootNamespace>
9 <AssemblyName>Implab</AssemblyName>
9 <AssemblyName>Implab</AssemblyName>
10 <ProductVersion>8.0.30703</ProductVersion>
11 <SchemaVersion>2.0</SchemaVersion>
10 </PropertyGroup>
12 </PropertyGroup>
11 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
13 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
12 <DebugSymbols>true</DebugSymbols>
14 <DebugSymbols>true</DebugSymbols>
13 <DebugType>full</DebugType>
15 <DebugType>full</DebugType>
14 <Optimize>false</Optimize>
16 <Optimize>false</Optimize>
15 <OutputPath>bin\Debug</OutputPath>
17 <OutputPath>bin\Debug</OutputPath>
16 <DefineConstants>TRACE;DEBUG;</DefineConstants>
18 <DefineConstants>TRACE;DEBUG;</DefineConstants>
17 <ErrorReport>prompt</ErrorReport>
19 <ErrorReport>prompt</ErrorReport>
18 <WarningLevel>4</WarningLevel>
20 <WarningLevel>4</WarningLevel>
19 <ConsolePause>false</ConsolePause>
21 <ConsolePause>false</ConsolePause>
20 <RunCodeAnalysis>true</RunCodeAnalysis>
22 <RunCodeAnalysis>true</RunCodeAnalysis>
21 </PropertyGroup>
23 </PropertyGroup>
22 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
24 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
23 <DebugType>full</DebugType>
25 <DebugType>full</DebugType>
24 <Optimize>true</Optimize>
26 <Optimize>true</Optimize>
25 <OutputPath>bin\Release</OutputPath>
27 <OutputPath>bin\Release</OutputPath>
26 <ErrorReport>prompt</ErrorReport>
28 <ErrorReport>prompt</ErrorReport>
27 <WarningLevel>4</WarningLevel>
29 <WarningLevel>4</WarningLevel>
28 <ConsolePause>false</ConsolePause>
30 <ConsolePause>false</ConsolePause>
29 </PropertyGroup>
31 </PropertyGroup>
30 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' ">
32 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' ">
31 <DebugSymbols>true</DebugSymbols>
33 <DebugSymbols>true</DebugSymbols>
32 <DebugType>full</DebugType>
34 <DebugType>full</DebugType>
33 <Optimize>false</Optimize>
35 <Optimize>false</Optimize>
34 <OutputPath>bin\Debug</OutputPath>
36 <OutputPath>bin\Debug</OutputPath>
35 <DefineConstants>TRACE;DEBUG;NET_4_5</DefineConstants>
37 <DefineConstants>TRACE;DEBUG;NET_4_5</DefineConstants>
36 <ErrorReport>prompt</ErrorReport>
38 <ErrorReport>prompt</ErrorReport>
37 <WarningLevel>4</WarningLevel>
39 <WarningLevel>4</WarningLevel>
38 <RunCodeAnalysis>true</RunCodeAnalysis>
40 <RunCodeAnalysis>true</RunCodeAnalysis>
39 <ConsolePause>false</ConsolePause>
41 <ConsolePause>false</ConsolePause>
40 </PropertyGroup>
42 </PropertyGroup>
41 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' ">
43 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' ">
42 <Optimize>true</Optimize>
44 <Optimize>true</Optimize>
43 <OutputPath>bin\Release</OutputPath>
45 <OutputPath>bin\Release</OutputPath>
44 <ErrorReport>prompt</ErrorReport>
46 <ErrorReport>prompt</ErrorReport>
45 <WarningLevel>4</WarningLevel>
47 <WarningLevel>4</WarningLevel>
46 <ConsolePause>false</ConsolePause>
48 <ConsolePause>false</ConsolePause>
47 <DefineConstants>NET_4_5</DefineConstants>
49 <DefineConstants>NET_4_5</DefineConstants>
48 </PropertyGroup>
50 </PropertyGroup>
49 <ItemGroup>
51 <ItemGroup>
50 <Reference Include="System" />
52 <Reference Include="System" />
51 <Reference Include="System.Xml" />
53 <Reference Include="System.Xml" />
52 </ItemGroup>
54 </ItemGroup>
53 <ItemGroup>
55 <ItemGroup>
54 <Compile Include="Component.cs" />
56 <Compile Include="Component.cs" />
55 <Compile Include="CustomEqualityComparer.cs" />
57 <Compile Include="CustomEqualityComparer.cs" />
56 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
58 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
57 <Compile Include="Diagnostics\EventText.cs" />
59 <Compile Include="Diagnostics\EventText.cs" />
58 <Compile Include="Diagnostics\IEventTextFormatter.cs" />
60 <Compile Include="Diagnostics\IEventTextFormatter.cs" />
59 <Compile Include="Diagnostics\LogChannel.cs" />
61 <Compile Include="Diagnostics\LogChannel.cs" />
60 <Compile Include="Diagnostics\LogicalOperation.cs" />
62 <Compile Include="Diagnostics\LogicalOperation.cs" />
61 <Compile Include="Diagnostics\TextFileListener.cs" />
63 <Compile Include="Diagnostics\TextFileListener.cs" />
62 <Compile Include="Diagnostics\TextListenerBase.cs" />
64 <Compile Include="Diagnostics\TextListenerBase.cs" />
63 <Compile Include="Diagnostics\TraceLog.cs" />
65 <Compile Include="Diagnostics\TraceLog.cs" />
64 <Compile Include="Diagnostics\TraceContext.cs" />
66 <Compile Include="Diagnostics\TraceContext.cs" />
65 <Compile Include="Diagnostics\TraceEvent.cs" />
67 <Compile Include="Diagnostics\TraceEvent.cs" />
66 <Compile Include="Diagnostics\TraceEventType.cs" />
68 <Compile Include="Diagnostics\TraceEventType.cs" />
67 <Compile Include="Disposable.cs" />
69 <Compile Include="Disposable.cs" />
68 <Compile Include="ICancellable.cs" />
70 <Compile Include="ICancellable.cs" />
69 <Compile Include="IProgressHandler.cs" />
71 <Compile Include="IProgressHandler.cs" />
70 <Compile Include="IProgressNotifier.cs" />
72 <Compile Include="IProgressNotifier.cs" />
71 <Compile Include="IPromiseT.cs" />
73 <Compile Include="IPromiseT.cs" />
72 <Compile Include="IPromise.cs" />
74 <Compile Include="IPromise.cs" />
73 <Compile Include="IServiceLocator.cs" />
75 <Compile Include="IServiceLocator.cs" />
74 <Compile Include="ITaskController.cs" />
76 <Compile Include="ITaskController.cs" />
75 <Compile Include="JSON\JSONElementContext.cs" />
77 <Compile Include="JSON\JSONElementContext.cs" />
76 <Compile Include="JSON\JSONElementType.cs" />
78 <Compile Include="JSON\JSONElementType.cs" />
77 <Compile Include="JSON\JSONGrammar.cs" />
79 <Compile Include="JSON\JSONGrammar.cs" />
78 <Compile Include="JSON\JSONParser.cs" />
80 <Compile Include="JSON\JSONParser.cs" />
79 <Compile Include="JSON\JSONScanner.cs" />
81 <Compile Include="JSON\JSONScanner.cs" />
80 <Compile Include="JSON\JsonTokenType.cs" />
82 <Compile Include="JSON\JsonTokenType.cs" />
81 <Compile Include="JSON\JSONWriter.cs" />
83 <Compile Include="JSON\JSONWriter.cs" />
82 <Compile Include="JSON\JSONXmlReader.cs" />
84 <Compile Include="JSON\JSONXmlReader.cs" />
83 <Compile Include="JSON\JSONXmlReaderOptions.cs" />
85 <Compile Include="JSON\JSONXmlReaderOptions.cs" />
84 <Compile Include="JSON\StringTranslator.cs" />
86 <Compile Include="JSON\StringTranslator.cs" />
85 <Compile Include="Parallels\DispatchPool.cs" />
87 <Compile Include="Parallels\DispatchPool.cs" />
86 <Compile Include="Parallels\ArrayTraits.cs" />
88 <Compile Include="Parallels\ArrayTraits.cs" />
87 <Compile Include="Parallels\MTQueue.cs" />
89 <Compile Include="Parallels\MTQueue.cs" />
88 <Compile Include="Parallels\WorkerPool.cs" />
90 <Compile Include="Parallels\WorkerPool.cs" />
89 <Compile Include="Parsing\Alphabet.cs" />
91 <Compile Include="Parsing\Alphabet.cs" />
90 <Compile Include="Parsing\AlphabetBase.cs" />
92 <Compile Include="Parsing\AlphabetBase.cs" />
91 <Compile Include="Parsing\AltToken.cs" />
93 <Compile Include="Parsing\AltToken.cs" />
92 <Compile Include="Parsing\BinaryToken.cs" />
94 <Compile Include="Parsing\BinaryToken.cs" />
93 <Compile Include="Parsing\CatToken.cs" />
95 <Compile Include="Parsing\CatToken.cs" />
94 <Compile Include="Parsing\CDFADefinition.cs" />
96 <Compile Include="Parsing\CDFADefinition.cs" />
95 <Compile Include="Parsing\DFABuilder.cs" />
97 <Compile Include="Parsing\DFABuilder.cs" />
96 <Compile Include="Parsing\DFADefinitionBase.cs" />
98 <Compile Include="Parsing\DFADefinitionBase.cs" />
97 <Compile Include="Parsing\DFAStateDescriptor.cs" />
99 <Compile Include="Parsing\DFAStateDescriptor.cs" />
98 <Compile Include="Parsing\DFAutomaton.cs" />
100 <Compile Include="Parsing\DFAutomaton.cs" />
99 <Compile Include="Parsing\EDFADefinition.cs" />
101 <Compile Include="Parsing\EDFADefinition.cs" />
100 <Compile Include="Parsing\EmptyToken.cs" />
102 <Compile Include="Parsing\EmptyToken.cs" />
101 <Compile Include="Parsing\EndToken.cs" />
103 <Compile Include="Parsing\EndToken.cs" />
102 <Compile Include="Parsing\EnumAlphabet.cs" />
104 <Compile Include="Parsing\EnumAlphabet.cs" />
103 <Compile Include="Parsing\Grammar.cs" />
105 <Compile Include="Parsing\Grammar.cs" />
104 <Compile Include="Parsing\IAlphabet.cs" />
106 <Compile Include="Parsing\IAlphabet.cs" />
105 <Compile Include="Parsing\IDFADefinition.cs" />
107 <Compile Include="Parsing\IDFADefinition.cs" />
106 <Compile Include="Parsing\IVisitor.cs" />
108 <Compile Include="Parsing\IVisitor.cs" />
107 <Compile Include="Parsing\ParserException.cs" />
109 <Compile Include="Parsing\ParserException.cs" />
108 <Compile Include="Parsing\Scanner.cs" />
110 <Compile Include="Parsing\Scanner.cs" />
109 <Compile Include="Parsing\StarToken.cs" />
111 <Compile Include="Parsing\StarToken.cs" />
110 <Compile Include="Parsing\SymbolToken.cs" />
112 <Compile Include="Parsing\SymbolToken.cs" />
111 <Compile Include="Parsing\Token.cs" />
113 <Compile Include="Parsing\Token.cs" />
112 <Compile Include="SafePool.cs" />
114 <Compile Include="SafePool.cs" />
113 <Compile Include="ServiceLocator.cs" />
115 <Compile Include="ServiceLocator.cs" />
114 <Compile Include="TaskController.cs" />
116 <Compile Include="TaskController.cs" />
115 <Compile Include="ProgressInitEventArgs.cs" />
117 <Compile Include="ProgressInitEventArgs.cs" />
116 <Compile Include="Properties\AssemblyInfo.cs" />
118 <Compile Include="Properties\AssemblyInfo.cs" />
117 <Compile Include="Promise.cs" />
119 <Compile Include="Promise.cs" />
118 <Compile Include="Parallels\AsyncPool.cs" />
120 <Compile Include="Parallels\AsyncPool.cs" />
119 <Compile Include="Safe.cs" />
121 <Compile Include="Safe.cs" />
120 <Compile Include="ValueEventArgs.cs" />
122 <Compile Include="ValueEventArgs.cs" />
121 <Compile Include="PromiseExtensions.cs" />
123 <Compile Include="PromiseExtensions.cs" />
122 <Compile Include="TransientPromiseException.cs" />
124 <Compile Include="TransientPromiseException.cs" />
123 <Compile Include="SyncContextPromise.cs" />
125 <Compile Include="SyncContextPromise.cs" />
126 <Compile Include="SyncPool.cs" />
127 <Compile Include="SyncPoolWrapper.cs" />
124 </ItemGroup>
128 </ItemGroup>
125 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
129 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
126 <ItemGroup />
130 <ItemGroup />
127 <ProjectExtensions>
131 <ProjectExtensions>
128 <MonoDevelop>
132 <MonoDevelop>
129 <Properties>
133 <Properties>
130 <Policies>
134 <Policies>
131 <CSharpFormattingPolicy IndentSwitchBody="True" NamespaceBraceStyle="EndOfLine" ClassBraceStyle="EndOfLine" InterfaceBraceStyle="EndOfLine" StructBraceStyle="EndOfLine" EnumBraceStyle="EndOfLine" MethodBraceStyle="EndOfLine" ConstructorBraceStyle="EndOfLine" DestructorBraceStyle="EndOfLine" BeforeMethodDeclarationParentheses="False" BeforeMethodCallParentheses="False" BeforeConstructorDeclarationParentheses="False" NewLineBeforeConstructorInitializerColon="NewLine" NewLineAfterConstructorInitializerColon="SameLine" BeforeIndexerDeclarationBracket="False" BeforeDelegateDeclarationParentheses="False" NewParentheses="False" SpacesBeforeBrackets="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
135 <CSharpFormattingPolicy IndentSwitchBody="True" NamespaceBraceStyle="EndOfLine" ClassBraceStyle="EndOfLine" InterfaceBraceStyle="EndOfLine" StructBraceStyle="EndOfLine" EnumBraceStyle="EndOfLine" MethodBraceStyle="EndOfLine" ConstructorBraceStyle="EndOfLine" DestructorBraceStyle="EndOfLine" BeforeMethodDeclarationParentheses="False" BeforeMethodCallParentheses="False" BeforeConstructorDeclarationParentheses="False" NewLineBeforeConstructorInitializerColon="NewLine" NewLineAfterConstructorInitializerColon="SameLine" BeforeIndexerDeclarationBracket="False" BeforeDelegateDeclarationParentheses="False" NewParentheses="False" SpacesBeforeBrackets="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
132 <TextStylePolicy FileWidth="120" EolMarker="Unix" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
136 <TextStylePolicy FileWidth="120" EolMarker="Unix" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
133 <DotNetNamingPolicy DirectoryNamespaceAssociation="PrefixedHierarchical" ResourceNamePolicy="MSBuild" />
137 <DotNetNamingPolicy DirectoryNamespaceAssociation="PrefixedHierarchical" ResourceNamePolicy="MSBuild" />
134 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="application/xml" />
138 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="application/xml" />
135 <XmlFormattingPolicy inheritsSet="Mono" inheritsScope="application/xml" scope="application/xml" />
139 <XmlFormattingPolicy inheritsSet="Mono" inheritsScope="application/xml" scope="application/xml" />
136 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" />
140 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" />
137 <NameConventionPolicy>
141 <NameConventionPolicy>
138 <Rules>
142 <Rules>
139 <NamingRule Name="Namespaces" AffectedEntity="Namespace" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
143 <NamingRule Name="Namespaces" AffectedEntity="Namespace" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
140 <NamingRule Name="Types" AffectedEntity="Class, Struct, Enum, Delegate" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
144 <NamingRule Name="Types" AffectedEntity="Class, Struct, Enum, Delegate" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
141 <NamingRule Name="Interfaces" AffectedEntity="Interface" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
145 <NamingRule Name="Interfaces" AffectedEntity="Interface" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
142 <RequiredPrefixes>
146 <RequiredPrefixes>
143 <String>I</String>
147 <String>I</String>
144 </RequiredPrefixes>
148 </RequiredPrefixes>
145 </NamingRule>
149 </NamingRule>
146 <NamingRule Name="Attributes" AffectedEntity="CustomAttributes" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
150 <NamingRule Name="Attributes" AffectedEntity="CustomAttributes" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
147 <RequiredSuffixes>
151 <RequiredSuffixes>
148 <String>Attribute</String>
152 <String>Attribute</String>
149 </RequiredSuffixes>
153 </RequiredSuffixes>
150 </NamingRule>
154 </NamingRule>
151 <NamingRule Name="Event Arguments" AffectedEntity="CustomEventArgs" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
155 <NamingRule Name="Event Arguments" AffectedEntity="CustomEventArgs" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
152 <RequiredSuffixes>
156 <RequiredSuffixes>
153 <String>EventArgs</String>
157 <String>EventArgs</String>
154 </RequiredSuffixes>
158 </RequiredSuffixes>
155 </NamingRule>
159 </NamingRule>
156 <NamingRule Name="Exceptions" AffectedEntity="CustomExceptions" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
160 <NamingRule Name="Exceptions" AffectedEntity="CustomExceptions" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
157 <RequiredSuffixes>
161 <RequiredSuffixes>
158 <String>Exception</String>
162 <String>Exception</String>
159 </RequiredSuffixes>
163 </RequiredSuffixes>
160 </NamingRule>
164 </NamingRule>
161 <NamingRule Name="Methods" AffectedEntity="Methods" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
165 <NamingRule Name="Methods" AffectedEntity="Methods" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
162 <NamingRule Name="Static Readonly Fields" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Protected, Public" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True" />
166 <NamingRule Name="Static Readonly Fields" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Protected, Public" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True" />
163 <NamingRule Name="Fields (Non Private)" AffectedEntity="Field" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
167 <NamingRule Name="Fields (Non Private)" AffectedEntity="Field" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
164 <NamingRule Name="ReadOnly Fields (Non Private)" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False" />
168 <NamingRule Name="ReadOnly Fields (Non Private)" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False" />
165 <NamingRule Name="Fields (Private)" AffectedEntity="Field, ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
169 <NamingRule Name="Fields (Private)" AffectedEntity="Field, ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
166 <RequiredPrefixes>
170 <RequiredPrefixes>
167 <String>m_</String>
171 <String>m_</String>
168 </RequiredPrefixes>
172 </RequiredPrefixes>
169 </NamingRule>
173 </NamingRule>
170 <NamingRule Name="Static Fields (Private)" AffectedEntity="Field" VisibilityMask="Private" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True">
174 <NamingRule Name="Static Fields (Private)" AffectedEntity="Field" VisibilityMask="Private" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True">
171 <RequiredPrefixes>
175 <RequiredPrefixes>
172 <String>_</String>
176 <String>_</String>
173 </RequiredPrefixes>
177 </RequiredPrefixes>
174 </NamingRule>
178 </NamingRule>
175 <NamingRule Name="ReadOnly Fields (Private)" AffectedEntity="ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
179 <NamingRule Name="ReadOnly Fields (Private)" AffectedEntity="ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
176 <RequiredPrefixes>
180 <RequiredPrefixes>
177 <String>m_</String>
181 <String>m_</String>
178 </RequiredPrefixes>
182 </RequiredPrefixes>
179 </NamingRule>
183 </NamingRule>
180 <NamingRule Name="Constant Fields" AffectedEntity="ConstantField" VisibilityMask="VisibilityMask" NamingStyle="AllUpper" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
184 <NamingRule Name="Constant Fields" AffectedEntity="ConstantField" VisibilityMask="VisibilityMask" NamingStyle="AllUpper" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
181 <NamingRule Name="Properties" AffectedEntity="Property" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
185 <NamingRule Name="Properties" AffectedEntity="Property" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
182 <NamingRule Name="Events" AffectedEntity="Event" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
186 <NamingRule Name="Events" AffectedEntity="Event" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
183 <NamingRule Name="Enum Members" AffectedEntity="EnumMember" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
187 <NamingRule Name="Enum Members" AffectedEntity="EnumMember" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
184 <NamingRule Name="Parameters" AffectedEntity="Parameter, LocalVariable" VisibilityMask="VisibilityMask" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
188 <NamingRule Name="Parameters" AffectedEntity="Parameter, LocalVariable" VisibilityMask="VisibilityMask" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
185 <NamingRule Name="Type Parameters" AffectedEntity="TypeParameter" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
189 <NamingRule Name="Type Parameters" AffectedEntity="TypeParameter" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
186 <RequiredPrefixes>
190 <RequiredPrefixes>
187 <String>T</String>
191 <String>T</String>
188 </RequiredPrefixes>
192 </RequiredPrefixes>
189 </NamingRule>
193 </NamingRule>
190 </Rules>
194 </Rules>
191 </NameConventionPolicy>
195 </NameConventionPolicy>
192 </Policies>
196 </Policies>
193 </Properties>
197 </Properties>
194 </MonoDevelop>
198 </MonoDevelop>
195 </ProjectExtensions>
199 </ProjectExtensions>
196 </Project> No newline at end of file
200 </Project>
@@ -1,62 +1,65
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.Xml;
5 using System.Xml;
6
6
7 namespace Implab.JSON {
7 namespace Implab.JSON {
8 /// <summary>
8 /// <summary>
9 /// Набор Π½Π΅ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² для <see cref="JSONXmlReader"/>, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΠΈΠΉ ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ процСссом
9 /// Набор Π½Π΅ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² для <see cref="JSONXmlReader"/>, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΠΈΠΉ ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ процСссом
10 /// ΠΈΠ½Ρ‚Π΅Ρ€ΠΏΡ€Π΅Ρ‚Π°Ρ†ΠΈΠΈ <c>JSON</c> Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°.
10 /// ΠΈΠ½Ρ‚Π΅Ρ€ΠΏΡ€Π΅Ρ‚Π°Ρ†ΠΈΠΈ <c>JSON</c> Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°.
11 /// </summary>
11 /// </summary>
12 public class JSONXmlReaderOptions {
12 public class JSONXmlReaderOptions {
13 /// <summary>
13 /// <summary>
14 /// ΠŸΡ€ΠΎΡΡ‚Ρ€Π°Π½ΡΡ‚Π²ΠΎ ΠΈΠΌΠ΅Π½ Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ Π±ΡƒΠ΄ΡƒΡ‚ Ρ€Π°ΡΠΏΠΎΠ»Π°Π³Π°Ρ‚ΡŒΡΡ Ρ‡ΠΈΡ‚Π°Π΅ΠΌΡ‹Π΅ элСмСнты Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°
14 /// ΠŸΡ€ΠΎΡΡ‚Ρ€Π°Π½ΡΡ‚Π²ΠΎ ΠΈΠΌΠ΅Π½ Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ Π±ΡƒΠ΄ΡƒΡ‚ Ρ€Π°ΡΠΏΠΎΠ»Π°Π³Π°Ρ‚ΡŒΡΡ Ρ‡ΠΈΡ‚Π°Π΅ΠΌΡ‹Π΅ элСмСнты Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°
15 /// </summary>
15 /// </summary>
16 public string NamespaceURI {
16 public string NamespaceURI {
17 get;
17 get;
18 set;
18 set;
19 }
19 }
20
20
21 /// <summary>
21 /// <summary>
22 /// Π˜Π½Ρ‚Π΅Ρ€ΠΏΡ€Π΅Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ массивы ΠΊΠ°ΠΊ мноТСствСнныС элСмСнты (ΡƒΠ±ΠΈΡ€Π°Π΅Ρ‚ ΠΎΠ΄ΠΈΠ½ ΡƒΡ€ΠΎΠ²Π΅Π½ΡŒ влоТСнности)
22 /// Π˜Π½Ρ‚Π΅Ρ€ΠΏΡ€Π΅Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ массивы ΠΊΠ°ΠΊ мноТСствСнныС элСмСнты (ΡƒΠ±ΠΈΡ€Π°Π΅Ρ‚ ΠΎΠ΄ΠΈΠ½ ΡƒΡ€ΠΎΠ²Π΅Π½ΡŒ влоТСнности), ΠΈΠ½Π°Ρ‡Π΅ массив
23 /// прСдставляСтся Π² Π²ΠΈΠ΄Π΅ ΡƒΠ·Π»Π°, Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΌΠΈ элСмСнтами ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ ΡΠ²Π»ΡΡŽΡ‚ΡΡ элСмСнты массива, ΠΈΠΌΠ΅Π½Π° Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΡ… элСмСнтов
24 /// ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‚ΡΡ свойством <see cref="ArrayItemName"/>. По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ <c>false</c>.
23 /// </summary>
25 /// </summary>
24 public bool FlattenArrays {
26 public bool FlattenArrays {
25 get;
27 get;
26 set;
28 set;
27 }
29 }
28
30
29 /// <summary>
31 /// <summary>
30 /// ΠŸΡ€Π΅Ρ„ΠΈΠΊΡ, для ΡƒΠ·Π»ΠΎΠ² Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°
32 /// ΠŸΡ€Π΅Ρ„ΠΈΠΊΡ, для ΡƒΠ·Π»ΠΎΠ² Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°
31 /// </summary>
33 /// </summary>
32 public string NodesPrefix {
34 public string NodesPrefix {
33 get;
35 get;
34 set;
36 set;
35 }
37 }
36
38
37 /// <summary>
39 /// <summary>
38 /// Имя ΠΊΠΎΡ€Π½Π΅Π²ΠΎΠ³ΠΎ элСмСнта Π² xml Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π΅
40 /// Имя ΠΊΠΎΡ€Π½Π΅Π²ΠΎΠ³ΠΎ элСмСнта Π² xml Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π΅
39 /// </summary>
41 /// </summary>
40 public string RootName {
42 public string RootName {
41 get;
43 get;
42 set;
44 set;
43 }
45 }
44
46
45 /// <summary>
47 /// <summary>
46 /// Имя элСмСнта для массивов, Ссли Π½Π΅ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Π° опция <see cref="FlattenArrays"/>.
48 /// Имя элСмСнта для массивов, Ссли Π½Π΅ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Π° опция <see cref="FlattenArrays"/>.
49 /// По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ <c>item</c>.
47 /// </summary>
50 /// </summary>
48 public string ArrayItemName {
51 public string ArrayItemName {
49 get;
52 get;
50 set;
53 set;
51 }
54 }
52
55
53 /// <summary>
56 /// <summary>
54 /// Π’Π°Π±Π»ΠΈΡ†Π° Π°Ρ‚ΠΎΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Ρ… строк для построСния Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°.
57 /// Π’Π°Π±Π»ΠΈΡ†Π° Π°Ρ‚ΠΎΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Ρ… строк для построСния Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°.
55 /// </summary>
58 /// </summary>
56 public XmlNameTable NameTable {
59 public XmlNameTable NameTable {
57 get;
60 get;
58 set;
61 set;
59 }
62 }
60
63
61 }
64 }
62 }
65 }
@@ -1,193 +1,200
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.Anyway(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.Anyway(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, ResultMapper<TSrc, IPromise<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 object locker = new object();
157 int slots = threads;
157
158
158 // Analysis disable AccessToDisposedClosure
159 // Analysis disable AccessToDisposedClosure
159 AsyncPool.InvokeNewThread(() => {
160 AsyncPool.InvokeNewThread(() => {
160 for (int i = 0; i < source.Length; i++) {
161 for (int i = 0; i < source.Length; i++) {
161 if(promise.IsResolved)
162 if(promise.IsResolved)
162 break; // stop processing in case of error or cancellation
163 break; // stop processing in case of error or cancellation
163 var idx = i;
164 var idx = i;
164
165
165 semaphore.WaitOne();
166 lock(locker) {
167 while(slots == 0)
168 Monitor.Wait(locker);
169 slots--;
170 }
166 try {
171 try {
167 var p1 = transform(source[i]);
172 transform(source[i])
168 p1.Anyway(() => semaphore.Release());
173 .Anyway(() => {
169 p1.Then(
174 lock(locker) {
175 slots ++;
176 Monitor.Pulse(locker);
177 }
178 })
179 .Last(
170 x => {
180 x => {
171 res[idx] = x;
181 res[idx] = x;
172 var left = Interlocked.Decrement(ref pending);
182 var left = Interlocked.Decrement(ref pending);
173 if (left == 0)
183 if (left == 0)
174 promise.Resolve(res);
184 promise.Resolve(res);
175 },
185 },
176 e => {
186 e => promise.Reject(e)
177 promise.Reject(e);
178 throw new TransientPromiseException(e);
179 }
180 );
187 );
181
188
182 } catch (Exception e) {
189 } catch (Exception e) {
183 promise.Reject(e);
190 promise.Reject(e);
184 }
191 }
185 }
192 }
186 return 0;
193 return 0;
187 });
194 });
188
195
189 return promise.Anyway(semaphore.Dispose);
196 return promise;
190 }
197 }
191
198
192 }
199 }
193 }
200 }
@@ -1,334 +1,343
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.Diagnostics;
6 using System.Diagnostics;
7
7
8 namespace Implab.Parallels {
8 namespace Implab.Parallels {
9 public abstract class DispatchPool<TUnit> : IDisposable {
9 public abstract class DispatchPool<TUnit> : IDisposable {
10 readonly int m_minThreads;
10 readonly int m_minThreads;
11 readonly int m_maxThreads;
11 readonly int m_maxThreads;
12 readonly int m_releaseTimeout = 100; // the timeout while the working thread will wait for the new tasks before exit
12
13
13 int m_createdThreads = 0; // the current size of the pool
14 int m_createdThreads = 0; // the current size of the pool
14 int m_activeThreads = 0; // the count of threads which are active
15 int m_activeThreads = 0; // the count of threads which are active
15 int m_sleepingThreads = 0; // the count of currently inactive threads
16 int m_sleepingThreads = 0; // the count of currently inactive threads
16 int m_maxRunningThreads = 0; // the meximum reached size of the pool
17 int m_maxRunningThreads = 0; // the meximum reached size of the pool
17 int m_exitRequired = 0; // the pool is going to shutdown, all unused workers are released
18 int m_exitRequired = 0; // the pool is going to shutdown, all unused workers are released
18 int m_releaseTimeout = 100; // the timeout while the working thread will wait for the new tasks before exit
19
19 int m_wakeEvents = 0; // the count of wake events
20 int m_wakeEvents = 0; // the count of wake events
20
21
21 AutoResetEvent m_hasTasks = new AutoResetEvent(false);
22 readonly object m_signalLocker = new object();
22
23
23 protected DispatchPool(int min, int max) {
24 protected DispatchPool(int min, int max) {
24 if (min < 0)
25 if (min < 0)
25 throw new ArgumentOutOfRangeException("min");
26 throw new ArgumentOutOfRangeException("min");
26 if (max <= 0)
27 if (max <= 0)
27 throw new ArgumentOutOfRangeException("max");
28 throw new ArgumentOutOfRangeException("max");
28
29
29 if (min > max)
30 if (min > max)
30 min = max;
31 min = max;
31 m_minThreads = min;
32 m_minThreads = min;
32 m_maxThreads = max;
33 m_maxThreads = max;
33 }
34 }
34
35
35 protected DispatchPool(int threads)
36 protected DispatchPool(int threads)
36 : this(threads, threads) {
37 : this(threads, threads) {
37 }
38 }
38
39
39 protected DispatchPool() {
40 protected DispatchPool() {
40 int maxThreads, maxCP;
41 int maxThreads, maxCP;
41 ThreadPool.GetMaxThreads(out maxThreads, out maxCP);
42 ThreadPool.GetMaxThreads(out maxThreads, out maxCP);
42
43
43 m_minThreads = 0;
44 m_minThreads = 0;
44 m_maxThreads = maxThreads;
45 m_maxThreads = maxThreads;
45 }
46 }
46
47
47 protected void InitPool() {
48 protected void InitPool() {
48 for (int i = 0; i < m_minThreads; i++)
49 for (int i = 0; i < m_minThreads; i++)
49 StartWorker();
50 StartWorker();
50 }
51 }
51
52
52 public int PoolSize {
53 public int PoolSize {
53 get {
54 get {
55 Thread.MemoryBarrier();
54 return m_createdThreads;
56 return m_createdThreads;
55 }
57 }
56 }
58 }
57
59
58 public int ActiveThreads {
60 public int ActiveThreads {
59 get {
61 get {
62 Thread.MemoryBarrier();
60 return m_activeThreads;
63 return m_activeThreads;
61 }
64 }
62 }
65 }
63
66
64 public int MaxRunningThreads {
67 public int MaxRunningThreads {
65 get {
68 get {
69 Thread.MemoryBarrier();
66 return m_maxRunningThreads;
70 return m_maxRunningThreads;
67 }
71 }
68 }
72 }
69
73
70 protected bool IsDisposed {
74 protected bool IsDisposed {
71 get {
75 get {
72 return m_exitRequired != 0;
76 Thread.MemoryBarrier();
77 return m_exitRequired == 1;
73 }
78 }
74 }
79 }
75
80
76 protected abstract bool TryDequeue(out TUnit unit);
81 protected abstract bool TryDequeue(out TUnit unit);
77
82
78 #region thread execution traits
83 #region thread signaling traits
79 int SignalThread() {
84 int SignalThread() {
80 var signals = Interlocked.Increment(ref m_wakeEvents);
85 var signals = Interlocked.Increment(ref m_wakeEvents);
81 if(signals == 1)
86 if(signals == 1)
82 m_hasTasks.Set();
87 lock(m_signalLocker)
88 Monitor.Pulse(m_signalLocker);
83 return signals;
89 return signals;
84 }
90 }
85
91
86 bool FetchSignalOrWait(int timeout) {
92 bool FetchSignalOrWait(int timeout) {
87 var start = Environment.TickCount;
93 var start = Environment.TickCount;
88
89 // ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΏΠΎΡ‚ΠΎΠΊ Π²Π»Π°Π΄Π΅Π΅Ρ‚ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΎΠΉ ΠΈ ΠΏΡ€ΠΈ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠΈ сигнала Π΄ΠΎΠ»ΠΆΠ΅Π½
90 // Π΅Π΅ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π΄Ρ€ΡƒΠ³ΠΎΠΉ ΠΎΠΆΠΈΠ΄Π°ΡŽΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ смог
91 bool hasLock = false;
92 do {
93 int signals;
94 int signals;
95 Thread.MemoryBarrier(); // m_wakeEvents volatile first read
94 do {
96 do {
95 signals = m_wakeEvents;
97 signals = m_wakeEvents;
96 if (signals == 0)
98 if (signals == 0)
97 break;
99 break;
98 } while (Interlocked.CompareExchange(ref m_wakeEvents, signals - 1, signals) != signals);
100 } while (Interlocked.CompareExchange(ref m_wakeEvents, signals - 1, signals) != signals);
99
101
100 if (signals >= 1) {
102 if (signals == 0) {
101 if (signals > 1 && hasLock)
103 // no signal is fetched
102 m_hasTasks.Set();
104 lock(m_signalLocker) {
105 while(m_wakeEvents == 0) {
106 if (timeout != -1)
107 timeout = Math.Max(0, timeout - (Environment.TickCount - start));
108 if(!Monitor.Wait(m_signalLocker,timeout))
109 return false; // timeout
110 }
111 // m_wakeEvents > 0
112 if (Interlocked.Decrement(ref m_wakeEvents) > 0) //syncronized
113 Monitor.Pulse(m_signalLocker);
114
115 // signal fetched
103 return true;
116 return true;
104 }
117 }
105
118
106 if (timeout != -1)
119 } else {
107 timeout = Math.Max(0, timeout - (Environment.TickCount - start));
120 // signal fetched
121 return true;
122 }
108
123
109 // Ссли сигналов большС Π½Π΅ ΠΎΡΡ‚Π°Π»ΠΎΡΡŒ, Ρ‚ΠΎ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ дошСл сюда сбросит событиС
110 // ΠΈ ΡƒΠΉΠ΄Π΅Ρ‚ Π½Π° пустой Ρ†ΠΈΠΊΠ», послС Ρ‡Π΅Π³ΠΎ заблокируСтся
111
124
112 hasLock = true;
113 } while (m_hasTasks.WaitOne(timeout));
114
115 return false;
116 }
125 }
117
126
118 bool Sleep(int timeout) {
127 bool Sleep(int timeout) {
119 Interlocked.Increment(ref m_sleepingThreads);
128 Interlocked.Increment(ref m_sleepingThreads);
120 if (FetchSignalOrWait(timeout)) {
129 if (FetchSignalOrWait(timeout)) {
121 Interlocked.Decrement(ref m_sleepingThreads);
130 Interlocked.Decrement(ref m_sleepingThreads);
122 return true;
131 return true;
123 } else {
132 } else {
124 Interlocked.Decrement(ref m_sleepingThreads);
133 Interlocked.Decrement(ref m_sleepingThreads);
125 return false;
134 return false;
126 }
135 }
127 }
136 }
128 #endregion
137 #endregion
129
138
130 /// <summary>
139 /// <summary>
131 /// ЗапускаСт Π»ΠΈΠ±ΠΎ Π½ΠΎΠ²Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ, Ссли Ρ€Π°Π½ΡŒΡˆΠ΅ Π½Π΅ Π±Ρ‹Π»ΠΎ Π½ΠΈ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ°, Π»ΠΈΠ±ΠΎ устанавливаСт событиС ΠΏΡ€ΠΎΠ±ΡƒΠΆΠ΄Π΅Π½ΠΈΠ΅ ΠΎΠ΄Π½ΠΎΠ³ΠΎ спящСго ΠΏΠΎΡ‚ΠΎΠΊΠ°
140 /// ЗапускаСт Π»ΠΈΠ±ΠΎ Π½ΠΎΠ²Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ, Ссли Ρ€Π°Π½ΡŒΡˆΠ΅ Π½Π΅ Π±Ρ‹Π»ΠΎ Π½ΠΈ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ°, Π»ΠΈΠ±ΠΎ устанавливаСт событиС ΠΏΡ€ΠΎΠ±ΡƒΠΆΠ΄Π΅Π½ΠΈΠ΅ ΠΎΠ΄Π½ΠΎΠ³ΠΎ спящСго ΠΏΠΎΡ‚ΠΎΠΊΠ°
132 /// </summary>
141 /// </summary>
133 protected void GrowPool() {
142 protected void GrowPool() {
134 if (m_exitRequired != 0)
143 Thread.MemoryBarrier();
144 if (m_exitRequired == 1)
135 return;
145 return;
136 if (m_sleepingThreads > m_wakeEvents) {
146 if (m_sleepingThreads > m_wakeEvents) {
137 //Console.WriteLine("Waking threads (sleeps {0}, pending {1})", m_sleepingThreads, m_wakeEvents);
147 //Console.WriteLine("Waking threads (sleeps {0}, pending {1})", m_sleepingThreads, m_wakeEvents);
138
148
139 // all sleeping threads may gone
149 // all sleeping threads may gone
140 SignalThread(); // wake a sleeping thread;
150 SignalThread(); // wake a sleeping thread;
141
151
142 // we can't check whether signal has been processed
152 // we can't check whether signal has been processed
143 // anyway it may take some time for the thread to start
153 // anyway it may take some time for the thread to start
144 // we will ensure that at least one thread is running
154 // we will ensure that at least one thread is running
145
155
146 EnsurePoolIsAlive();
156 EnsurePoolIsAlive();
147 } else {
157 } else {
148 // if there is no sleeping threads in the pool
158 // if there is no sleeping threads in the pool
149 if (!StartWorker()) {
159 if (!StartWorker()) {
150 // we haven't started a new thread, but the current can be on the way to terminate and it can't process the queue
160 // we haven't started a new thread, but the current can be on the way to terminate and it can't process the queue
151 // send it a signal to spin again
161 // send it a signal to spin again
152 SignalThread();
162 SignalThread();
153 EnsurePoolIsAlive();
163 EnsurePoolIsAlive();
154 }
164 }
155 }
165 }
156 }
166 }
157
167
158 protected void EnsurePoolIsAlive() {
168 protected void EnsurePoolIsAlive() {
159 if (AllocateThreadSlot(1)) {
169 if (AllocateThreadSlot(1)) {
160 // if there were no threads in the pool
170 // if there were no threads in the pool
161 var worker = new Thread(this.Worker);
171 var worker = new Thread(this.Worker);
162 worker.IsBackground = true;
172 worker.IsBackground = true;
163 worker.Start();
173 worker.Start();
164 }
174 }
165 }
175 }
166
176
167 protected virtual bool Suspend() {
177 protected virtual bool Suspend() {
168 //no tasks left, exit if the thread is no longer needed
178 //no tasks left, exit if the thread is no longer needed
169 bool last;
179 bool last;
170 bool requestExit;
180 bool requestExit;
171
181
172 // if threads have a timeout before releasing
182 // if threads have a timeout before releasing
173 if (m_releaseTimeout > 0)
183 if (m_releaseTimeout > 0)
174 requestExit = !Sleep(m_releaseTimeout);
184 requestExit = !Sleep(m_releaseTimeout);
175 else
185 else
176 requestExit = true;
186 requestExit = true;
177
187
178 if (!requestExit)
188 if (!requestExit)
179 return true;
189 return true;
180
190
181 // release unsused thread
191 // release unsused thread
182 if (requestExit && ReleaseThreadSlot(out last)) {
192 if (requestExit && ReleaseThreadSlot(out last)) {
183 // in case at the moment the last thread was being released
193 // in case at the moment the last thread was being released
184 // a new task was added to the queue, we need to try
194 // a new task was added to the queue, we need to try
185 // to revoke the thread to avoid the situation when the task is left unprocessed
195 // to revoke the thread to avoid the situation when the task is left unprocessed
186 if (last && FetchSignalOrWait(0)) { // FetchSignalOrWait(0) will fetch pending task or will return false
196 if (last && FetchSignalOrWait(0)) { // FetchSignalOrWait(0) will fetch pending task or will return false
187 SignalThread(); // since FetchSignalOrWait(0) has fetched the signal we need to reschedule it
197 SignalThread(); // since FetchSignalOrWait(0) has fetched the signal we need to reschedule it
188 return AllocateThreadSlot(1); // ensure that at least one thread is alive
198 return AllocateThreadSlot(1); // ensure that at least one thread is alive
189 }
199 }
190
200
191 return false;
201 return false;
192 }
202 }
193
203
194 // wait till infinity
204 // wait till infinity
195 Sleep(-1);
205 Sleep(-1);
196
206
197 return true;
207 return true;
198 }
208 }
199
209
200 #region thread slots traits
210 #region thread slots traits
201
211
202 bool AllocateThreadSlot() {
212 bool AllocateThreadSlot() {
203 int current;
213 int current;
204 // use spins to allocate slot for the new thread
214 // use spins to allocate slot for the new thread
205 do {
215 do {
206 current = m_createdThreads;
216 current = m_createdThreads;
207 if (current >= m_maxThreads || m_exitRequired != 0)
217 if (current >= m_maxThreads || m_exitRequired == 1)
208 // no more slots left or the pool has been disposed
218 // no more slots left or the pool has been disposed
209 return false;
219 return false;
210 } while (current != Interlocked.CompareExchange(ref m_createdThreads, current + 1, current));
220 } while (current != Interlocked.CompareExchange(ref m_createdThreads, current + 1, current));
211
221
212 UpdateMaxThreads(current + 1);
222 UpdateMaxThreads(current + 1);
213
223
214 return true;
224 return true;
215 }
225 }
216
226
217 bool AllocateThreadSlot(int desired) {
227 bool AllocateThreadSlot(int desired) {
218 if (desired - 1 != Interlocked.CompareExchange(ref m_createdThreads, desired, desired - 1))
228 if (desired - 1 != Interlocked.CompareExchange(ref m_createdThreads, desired, desired - 1))
219 return false;
229 return false;
220
230
221 UpdateMaxThreads(desired);
231 UpdateMaxThreads(desired);
222
232
223 return true;
233 return true;
224 }
234 }
225
235
226 bool ReleaseThreadSlot(out bool last) {
236 bool ReleaseThreadSlot(out bool last) {
227 last = false;
237 last = false;
228 int current;
238 int current;
229 // use spins to release slot for the new thread
239 // use spins to release slot for the new thread
240 Thread.MemoryBarrier();
230 do {
241 do {
231 current = m_createdThreads;
242 current = m_createdThreads;
232 if (current <= m_minThreads && m_exitRequired == 0)
243 if (current <= m_minThreads && m_exitRequired == 0)
233 // the thread is reserved
244 // the thread is reserved
234 return false;
245 return false;
235 } while (current != Interlocked.CompareExchange(ref m_createdThreads, current - 1, current));
246 } while (current != Interlocked.CompareExchange(ref m_createdThreads, current - 1, current));
236
247
237 last = (current == 1);
248 last = (current == 1);
238
249
239 return true;
250 return true;
240 }
251 }
241
252
242 /// <summary>
253 /// <summary>
243 /// releases thread slot unconditionally, used during cleanup
254 /// releases thread slot unconditionally, used during cleanup
244 /// </summary>
255 /// </summary>
245 /// <returns>true - no more threads left</returns>
256 /// <returns>true - no more threads left</returns>
246 bool ReleaseThreadSlotAnyway() {
257 bool ReleaseThreadSlotAnyway() {
247 var left = Interlocked.Decrement(ref m_createdThreads);
258 var left = Interlocked.Decrement(ref m_createdThreads);
248 return left == 0;
259 return left == 0;
249 }
260 }
250
261
251 void UpdateMaxThreads(int count) {
262 void UpdateMaxThreads(int count) {
252 int max;
263 int max;
253 do {
264 do {
254 max = m_maxRunningThreads;
265 max = m_maxRunningThreads;
255 if (max >= count)
266 if (max >= count)
256 break;
267 break;
257 } while(max != Interlocked.CompareExchange(ref m_maxRunningThreads, count, max));
268 } while(max != Interlocked.CompareExchange(ref m_maxRunningThreads, count, max));
258 }
269 }
259
270
260 #endregion
271 #endregion
261
272
262 bool StartWorker() {
273 bool StartWorker() {
263 if (AllocateThreadSlot()) {
274 if (AllocateThreadSlot()) {
264 // slot successfully allocated
275 // slot successfully allocated
265 var worker = new Thread(this.Worker);
276 var worker = new Thread(this.Worker);
266 worker.IsBackground = true;
277 worker.IsBackground = true;
278 Interlocked.Increment(ref m_activeThreads);
267 worker.Start();
279 worker.Start();
268
280
269 return true;
281 return true;
270 } else {
282 } else {
271 return false;
283 return false;
272 }
284 }
273 }
285 }
274
286
275 protected abstract void InvokeUnit(TUnit unit);
287 protected abstract void InvokeUnit(TUnit unit);
276
288
277 protected virtual void Worker() {
289 protected virtual void Worker() {
278 TUnit unit;
290 TUnit unit;
279 //Console.WriteLine("{0}: Active", Thread.CurrentThread.ManagedThreadId);
291 //Console.WriteLine("{0}: Active", Thread.CurrentThread.ManagedThreadId);
280 Interlocked.Increment(ref m_activeThreads);
292 int count = 0;;
293 Thread.MemoryBarrier();
281 do {
294 do {
282 // exit if requested
295 // exit if requested
283 if (m_exitRequired != 0) {
296 if (m_exitRequired == 1) {
284 // release the thread slot
297 // release the thread slot
285 Interlocked.Decrement(ref m_activeThreads);
298 Interlocked.Decrement(ref m_activeThreads);
286 if (ReleaseThreadSlotAnyway()) // it was the last worker
299 if (!ReleaseThreadSlotAnyway()) // it was the last worker
287 m_hasTasks.Dispose();
288 else
289 SignalThread(); // wake next worker
300 SignalThread(); // wake next worker
290 break;
301 break;
291 }
302 }
292
303
293 // fetch task
304 // fetch task
294 if (TryDequeue(out unit)) {
305 if (TryDequeue(out unit)) {
295 InvokeUnit(unit);
306 InvokeUnit(unit);
307 count ++;
296 continue;
308 continue;
297 }
309 }
298 Interlocked.Decrement(ref m_activeThreads);
310 Interlocked.Decrement(ref m_activeThreads);
299
311
312 Console.WriteLine("{0}: Suspend processed({1})", Thread.CurrentThread.ManagedThreadId,count);
300 // entering suspend state
313 // entering suspend state
301 // keep this thread and wait
314 // keep this thread and wait
302 if (!Suspend())
315 if (!Suspend())
303 break;
316 break;
317 count = 0;
304 //Console.WriteLine("{0}: Awake", Thread.CurrentThread.ManagedThreadId);
318 //Console.WriteLine("{0}: Awake", Thread.CurrentThread.ManagedThreadId);
305 Interlocked.Increment(ref m_activeThreads);
319 Interlocked.Increment(ref m_activeThreads);
306 } while (true);
320 } while (true);
307 //Console.WriteLine("{0}: Exited", Thread.CurrentThread.ManagedThreadId);
321 //Console.WriteLine("{0}: Exited", Thread.CurrentThread.ManagedThreadId);
308 }
322 }
309
323
310 protected virtual void Dispose(bool disposing) {
324 protected virtual void Dispose(bool disposing) {
311 if (disposing) {
325 if (disposing) {
312 if (m_exitRequired == 0) {
326 if (0 == Interlocked.CompareExchange(ref m_exitRequired, 1, 0)) { // implies memory barrier
313 if (Interlocked.CompareExchange(ref m_exitRequired, 1, 0) != 0)
314 return;
315
316 // wake sleeping threads
327 // wake sleeping threads
317 if (m_createdThreads > 0)
328 if (m_createdThreads > 0)
318 SignalThread();
329 SignalThread();
319 else
320 m_hasTasks.Dispose();
321 GC.SuppressFinalize(this);
330 GC.SuppressFinalize(this);
322 }
331 }
323 }
332 }
324 }
333 }
325
334
326 public void Dispose() {
335 public void Dispose() {
327 Dispose(true);
336 Dispose(true);
328 }
337 }
329
338
330 ~DispatchPool() {
339 ~DispatchPool() {
331 Dispose(false);
340 Dispose(false);
332 }
341 }
333 }
342 }
334 }
343 }
@@ -1,75 +1,78
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.Parallels {
7 namespace Implab.Parallels {
8 public class MTQueue<T> {
8 public class MTQueue<T> {
9 class Node {
9 class Node {
10 public Node(T value) {
10 public Node(T value) {
11 this.value = value;
11 this.value = value;
12 }
12 }
13 public readonly T value;
13 public readonly T value;
14 public Node next;
14 public Node next;
15 }
15 }
16
16
17 Node m_first;
17 Node m_first;
18 Node m_last;
18 Node m_last;
19
19
20 public void Enqueue(T value) {
20 public void Enqueue(T value) {
21 Thread.MemoryBarrier();
22
21 var last = m_last;
23 var last = m_last;
22 var next = new Node(value);
24 var next = new Node(value);
23
25
24 while (last != Interlocked.CompareExchange(ref m_last, next, last))
26 while (last != Interlocked.CompareExchange(ref m_last, next, last))
25 last = m_last;
27 last = m_last;
26
28
27 if (last != null)
29 if (last != null)
28 last.next = next;
30 last.next = next;
29 else
31 else
30 m_first = next;
32 m_first = next;
31 }
33 }
32
34
33 public bool TryDequeue(out T value) {
35 public bool TryDequeue(out T value) {
34 Node first;
36 Node first;
35 Node next = null;
37 Node next = null;
36 value = default(T);
38 value = default(T);
37
39
40 Thread.MemoryBarrier();
38 do {
41 do {
39 first = m_first;
42 first = m_first;
40 if (first == null)
43 if (first == null)
41 return false;
44 return false;
42 next = first.next;
45 next = first.next;
43 if (next == null) {
46 if (next == null) {
44 // this is the last element,
47 // this is the last element,
45 // then try to update the tail
48 // then try to update the tail
46 if (first != Interlocked.CompareExchange(ref m_last, null, first)) {
49 if (first != Interlocked.CompareExchange(ref m_last, null, first)) {
47 // this is the race condition
50 // this is the race condition
48 if (m_last == null)
51 if (m_last == null)
49 // the queue is empty
52 // the queue is empty
50 return false;
53 return false;
51 // tail has been changed, we need to restart
54 // tail has been changed, we need to restart
52 continue;
55 continue;
53 }
56 }
54
57
55 // tail succesfully updated and first.next will never be changed
58 // tail succesfully updated and first.next will never be changed
56 // other readers will fail due to inconsistency m_last != m_fist && m_first.next == null
59 // other readers will fail due to inconsistency m_last != m_fist && m_first.next == null
57 // however the parallel writer may update the m_first since the m_last is null
60 // however the parallel writer may update the m_first since the m_last is null
58
61
59 // so we need to fix inconsistency by setting m_first to null or if it has been
62 // so we need to fix inconsistency by setting m_first to null or if it has been
60 // updated by the writer already then we should just to give up
63 // updated by the writer already then we should just to give up
61 Interlocked.CompareExchange(ref m_first, null, first);
64 Interlocked.CompareExchange(ref m_first, null, first);
62 break;
65 break;
63
66
64 } else {
67 } else {
65 if (first == Interlocked.CompareExchange(ref m_first, next, first))
68 if (first == Interlocked.CompareExchange(ref m_first, next, first))
66 // head succesfully updated
69 // head succesfully updated
67 break;
70 break;
68 }
71 }
69 } while (true);
72 } while (true);
70
73
71 value = first.value;
74 value = first.value;
72 return true;
75 return true;
73 }
76 }
74 }
77 }
75 }
78 }
@@ -1,98 +1,106
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.Diagnostics;
6 using System.Diagnostics;
7 using Implab.Diagnostics;
7 using Implab.Diagnostics;
8
8
9 namespace Implab.Parallels {
9 namespace Implab.Parallels {
10 public class WorkerPool : DispatchPool<Action> {
10 public class WorkerPool : DispatchPool<Action> {
11
11
12 MTQueue<Action> m_queue = new MTQueue<Action>();
12 MTQueue<Action> m_queue = new MTQueue<Action>();
13 int m_queueLength = 0;
13 int m_queueLength = 0;
14 readonly int m_threshold = 1;
14 readonly int m_threshold = 1;
15 int m_workers = 0;
15
16
16 public WorkerPool(int minThreads, int maxThreads, int threshold)
17 public WorkerPool(int minThreads, int maxThreads, int threshold)
17 : base(minThreads, maxThreads) {
18 : base(minThreads, maxThreads) {
18 m_threshold = threshold;
19 m_threshold = threshold;
20 m_workers = minThreads;
19 InitPool();
21 InitPool();
20 }
22 }
21
23
22 public WorkerPool(int minThreads, int maxThreads) :
24 public WorkerPool(int minThreads, int maxThreads) :
23 base(minThreads, maxThreads) {
25 base(minThreads, maxThreads) {
26 m_workers = minThreads;
24 InitPool();
27 InitPool();
25 }
28 }
26
29
27 public WorkerPool(int threads)
30 public WorkerPool(int threads)
28 : base(threads) {
31 : base(threads) {
32 m_workers = threads;
29 InitPool();
33 InitPool();
30 }
34 }
31
35
32 public WorkerPool()
36 public WorkerPool()
33 : base() {
37 : base() {
34 InitPool();
38 InitPool();
35 }
39 }
36
40
37 public Promise<T> Invoke<T>(Func<T> task) {
41 public Promise<T> Invoke<T>(Func<T> task) {
38 if (task == null)
42 if (task == null)
39 throw new ArgumentNullException("task");
43 throw new ArgumentNullException("task");
40 if (IsDisposed)
44 if (IsDisposed)
41 throw new ObjectDisposedException(ToString());
45 throw new ObjectDisposedException(ToString());
42
46
43 var promise = new Promise<T>();
47 var promise = new Promise<T>();
44
48
45 var caller = TraceContext.Snapshot();
49 var caller = TraceContext.Snapshot();
46
50
47 EnqueueTask(delegate() {
51 EnqueueTask(delegate() {
48 caller.Invoke(delegate() {
52 caller.Invoke(delegate() {
49 try {
53 try {
50 promise.Resolve(task());
54 promise.Resolve(task());
51 } catch (Exception e) {
55 } catch (Exception e) {
52 promise.Reject(e);
56 promise.Reject(e);
53 }
57 }
54 });
58 });
55 });
59 });
56
60
57 return promise;
61 return promise;
58 }
62 }
59
63
60 protected void EnqueueTask(Action unit) {
64 protected void EnqueueTask(Action unit) {
61 Debug.Assert(unit != null);
65 Debug.Assert(unit != null);
62 var len = Interlocked.Increment(ref m_queueLength);
66 var len = Interlocked.Increment(ref m_queueLength);
63 m_queue.Enqueue(unit);
67 m_queue.Enqueue(unit);
64
68
65 if (len > m_threshold*ActiveThreads)
69 if (len > m_threshold * m_workers) {
70 Interlocked.Increment(ref m_workers);
66 GrowPool();
71 GrowPool();
67 }
72 }
73 }
68
74
69 protected override bool TryDequeue(out Action unit) {
75 protected override bool TryDequeue(out Action unit) {
70 if (m_queue.TryDequeue(out unit)) {
76 if (m_queue.TryDequeue(out unit)) {
71 Interlocked.Decrement(ref m_queueLength);
77 Interlocked.Decrement(ref m_queueLength);
72 return true;
78 return true;
73 }
79 }
74 return false;
80 return false;
75 }
81 }
76
82
77 protected override bool Suspend() {
83 protected override bool Suspend() {
78 // This override solves race condition
84 // This override solves race condition
79 // WORKER CLIENT
85 // WORKER CLIENT
80 // ---------------------------------------
86 // ---------------------------------------
81 // TryDeque == false
87 // TryDeque == false
82 // Enqueue(unit), queueLen++
88 // Enqueue(unit), queueLen++
83 // GrowPool? == NO
89 // GrowPool? == NO
84 // ActiveThreads--
90 // ActiveThreads--
85 // Suspend
91 // Suspend
86 // queueLength > 0
92 // queueLength > 0
87 // continue
93 // continue
94 Thread.MemoryBarrier();
88 if (m_queueLength > 0)
95 if (m_queueLength > 0)
89 return true;
96 return true;
97 Interlocked.Decrement(ref m_workers);
90 return base.Suspend();
98 return base.Suspend();
91 }
99 }
92
100
93 protected override void InvokeUnit(Action unit) {
101 protected override void InvokeUnit(Action unit) {
94 unit();
102 unit();
95 }
103 }
96
104
97 }
105 }
98 }
106 }
@@ -1,820 +1,822
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
14
15 /// <summary>
15 /// <summary>
16 /// Класс для асинхронного получСния Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ². Π’Π°ΠΊ Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΠΎΠ΅ "ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅".
16 /// Класс для асинхронного получСния Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ². Π’Π°ΠΊ Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΠΎΠ΅ "ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅".
17 /// </summary>
17 /// </summary>
18 /// <typeparam name="T">Π’ΠΈΠΏ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌΠΎΠ³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°</typeparam>
18 /// <typeparam name="T">Π’ΠΈΠΏ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌΠΎΠ³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°</typeparam>
19 /// <remarks>
19 /// <remarks>
20 /// <para>БСрвис ΠΏΡ€ΠΈ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ ΠΊ Π΅Π³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρƒ Π΄Π°Π΅Ρ‚ ΠΎΠ±Π΅Ρ‰Π°ΠΈΠ½ΠΈΠ΅ ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ,
20 /// <para>БСрвис ΠΏΡ€ΠΈ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ ΠΊ Π΅Π³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρƒ Π΄Π°Π΅Ρ‚ ΠΎΠ±Π΅Ρ‰Π°ΠΈΠ½ΠΈΠ΅ ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ,
21 /// ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ² Ρ‚Π°ΠΊΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ряд ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹Ρ… Π²Ρ‹Π·ΠΎΠ²ΠΎ для получСния
21 /// ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ² Ρ‚Π°ΠΊΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ряд ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹Ρ… Π²Ρ‹Π·ΠΎΠ²ΠΎ для получСния
22 /// событий выполнСния обСщания, Ρ‚ΠΎΠ΅ΡΡ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΈ прСдоставлСнии Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ².</para>
22 /// событий выполнСния обСщания, Ρ‚ΠΎΠ΅ΡΡ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΈ прСдоставлСнии Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ².</para>
23 /// <para>
23 /// <para>
24 /// ΠžΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚Π°ΠΊ ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ с ошибкой. Для подписки Π½Π°
24 /// ΠžΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚Π°ΠΊ ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ с ошибкой. Для подписки Π½Π°
25 /// Π΄Π°Π½Π½Ρ‹Π΅ события ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Then</c>.
25 /// Π΄Π°Π½Π½Ρ‹Π΅ события ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Then</c>.
26 /// </para>
26 /// </para>
27 /// <para>
27 /// <para>
28 /// БСрвис, Π² свою ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ, ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ (Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ с ошибкой),
28 /// БСрвис, Π² свою ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ, ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ (Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ с ошибкой),
29 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Resolve</c> Π»ΠΈΠ±ΠΎ <c>Reject</c> для оповСщСния ΠΊΠ»ΠΈΠ΅Ρ‚Π½Π° ΠΎ
29 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Resolve</c> Π»ΠΈΠ±ΠΎ <c>Reject</c> для оповСщСния ΠΊΠ»ΠΈΠ΅Ρ‚Π½Π° ΠΎ
30 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ обСщания.
30 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ обСщания.
31 /// </para>
31 /// </para>
32 /// <para>
32 /// <para>
33 /// Если сСрвСр успСл Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΅Ρ‰Π΅ Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π½Π° Π½Π΅Π³ΠΎ подписался,
33 /// Если сСрвСр успСл Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΅Ρ‰Π΅ Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π½Π° Π½Π΅Π³ΠΎ подписался,
34 /// Ρ‚ΠΎ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ подписки ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΠ²ΡƒΡŽΡ‰ΠΈΠ΅ события Π² синхронном
34 /// Ρ‚ΠΎ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ подписки ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΠ²ΡƒΡŽΡ‰ΠΈΠ΅ события Π² синхронном
35 /// Ρ€Π΅ΠΆΠΈΠΌΠ΅ ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΠΎΠ²Π΅Ρ‰Π΅Π½ Π² любом случаС. Π˜Π½Π°Ρ‡Π΅, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ΡΡ Π²
35 /// Ρ€Π΅ΠΆΠΈΠΌΠ΅ ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΠΎΠ²Π΅Ρ‰Π΅Π½ Π² любом случаС. Π˜Π½Π°Ρ‡Π΅, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ΡΡ Π²
36 /// список Π² порядкС подписания ΠΈ Π² этом ΠΆΠ΅ порядкС ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ
36 /// список Π² порядкС подписания ΠΈ Π² этом ΠΆΠ΅ порядкС ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ
37 /// обСщания.
37 /// обСщания.
38 /// </para>
38 /// </para>
39 /// <para>
39 /// <para>
40 /// ΠžΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ обСщания ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Π»ΠΈΠ±ΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ
40 /// ΠžΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ обСщания ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Π»ΠΈΠ±ΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ
41 /// связанныС асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ‚Π°ΠΊΠΆΠ΅ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ обСщания. Для этого слСдуСт
41 /// связанныС асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ‚Π°ΠΊΠΆΠ΅ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ обСщания. Для этого слСдуСт
42 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ Ρ„ΠΎΡ€ΠΌΡƒ ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ <c>Then</c>.
42 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ Ρ„ΠΎΡ€ΠΌΡƒ ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ <c>Then</c>.
43 /// </para>
43 /// </para>
44 /// <para>
44 /// <para>
45 /// Π’Π°ΠΊΠΆΠ΅ Ρ…ΠΎΡ€ΠΎΡˆΠΈΠΌ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎΠΌ являСтся Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ <c>Resolve</c> ΠΈ <c>Reject</c> Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ
45 /// Π’Π°ΠΊΠΆΠ΅ Ρ…ΠΎΡ€ΠΎΡˆΠΈΠΌ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎΠΌ являСтся Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ <c>Resolve</c> ΠΈ <c>Reject</c> Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ
46 /// Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€ обСщания ΠΈΠ½Π°Ρ‡Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ΡŒ противорСчия.
46 /// Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€ обСщания ΠΈΠ½Π°Ρ‡Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ΡŒ противорСчия.
47 /// </para>
47 /// </para>
48 /// </remarks>
48 /// </remarks>
49 public class Promise<T> : IPromise<T> {
49 public class Promise<T> : IPromise<T> {
50
50
51 protected struct HandlerDescriptor {
51 protected struct HandlerDescriptor {
52 public ResultHandler<T> resultHandler;
52 public ResultHandler<T> resultHandler;
53 public ErrorHandler<T> errorHandler;
53 public ErrorHandler<T> errorHandler;
54 public Action cancellHandler;
54 public Action cancellHandler;
55 public Promise<T> medium;
55 public Promise<T> medium;
56
56
57 public void Resolve(T result) {
57 public void Resolve(T result) {
58 if (resultHandler != null) {
58 if (resultHandler != null) {
59 try {
59 try {
60 resultHandler(result);
60 resultHandler(result);
61 } catch (Exception e) {
61 } catch (Exception e) {
62 Reject(e);
62 Reject(e);
63 return;
63 return;
64 }
64 }
65 }
65 }
66 if (medium != null)
66 if (medium != null)
67 medium.Resolve(result);
67 medium.Resolve(result);
68 }
68 }
69
69
70 public void Reject(Exception err) {
70 public void Reject(Exception err) {
71 if (errorHandler != null) {
71 if (errorHandler != null) {
72 try {
72 try {
73 var res = errorHandler(err);
73 var res = errorHandler(err);
74 if (medium != null)
74 if (medium != null)
75 medium.Resolve(res);
75 medium.Resolve(res);
76 } catch (TransientPromiseException err2) {
76 } catch (TransientPromiseException err2) {
77 if (medium != null)
77 if (medium != null)
78 medium.Reject(err2.InnerException);
78 medium.Reject(err2.InnerException);
79 } catch (Exception err2) {
79 } catch (Exception err2) {
80 if (medium != null)
80 if (medium != null)
81 medium.Reject(err2);
81 medium.Reject(err2);
82 }
82 }
83 } else if (medium != null)
83 } else if (medium != null)
84 medium.Reject(err);
84 medium.Reject(err);
85 }
85 }
86
86
87 public void Cancel() {
87 public void Cancel() {
88 if (cancellHandler != null) {
88 if (cancellHandler != null) {
89 try {
89 try {
90 cancellHandler();
90 cancellHandler();
91 } catch (Exception err) {
91 } catch (Exception err) {
92 Reject(err);
92 Reject(err);
93 return;
93 return;
94 }
94 }
95 }
95 }
96 if (medium != null)
96 if (medium != null)
97 medium.Cancel();
97 medium.Cancel();
98 }
98 }
99 }
99 }
100
100
101 const int UNRESOLVED_SATE = 0;
101 const int UNRESOLVED_SATE = 0;
102 const int TRANSITIONAL_STATE = 1;
102 const int TRANSITIONAL_STATE = 1;
103 const int SUCCEEDED_STATE = 2;
103 const int SUCCEEDED_STATE = 2;
104 const int REJECTED_STATE = 3;
104 const int REJECTED_STATE = 3;
105 const int CANCELLED_STATE = 4;
105 const int CANCELLED_STATE = 4;
106
106
107 readonly bool m_cancellable;
107 readonly bool m_cancellable;
108
108
109 int m_childrenCount = 0;
109 int m_childrenCount = 0;
110 int m_state;
110 int m_state;
111 T m_result;
111 T m_result;
112 Exception m_error;
112 Exception m_error;
113
113
114 readonly MTQueue<HandlerDescriptor> m_handlers = new MTQueue<HandlerDescriptor>();
114 readonly MTQueue<HandlerDescriptor> m_handlers = new MTQueue<HandlerDescriptor>();
115
115
116 public Promise() {
116 public Promise() {
117 m_cancellable = true;
117 m_cancellable = true;
118 }
118 }
119
119
120 public Promise(IPromise parent, bool cancellable) {
120 public Promise(IPromise parent, bool cancellable) {
121 m_cancellable = cancellable;
121 m_cancellable = cancellable;
122 if (parent != null)
122 if (parent != null)
123 AddHandler(
123 AddHandler(
124 null,
124 null,
125 null,
125 null,
126 () => {
126 () => {
127 if (parent.IsExclusive)
127 if (parent.IsExclusive)
128 parent.Cancel();
128 parent.Cancel();
129 },
129 },
130 null
130 null
131 );
131 );
132 }
132 }
133
133
134 bool BeginTransit() {
134 bool BeginTransit() {
135 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);
136 }
136 }
137
137
138 void CompleteTransit(int state) {
138 void CompleteTransit(int state) {
139 if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, state, TRANSITIONAL_STATE))
139 if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, state, TRANSITIONAL_STATE))
140 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");
141 }
141 }
142
142
143 void WaitTransition() {
143 void WaitTransition() {
144 while (m_state == TRANSITIONAL_STATE) {
144 while (m_state == TRANSITIONAL_STATE) {
145 /* noop */
145 Thread.MemoryBarrier();
146 }
146 }
147 }
147 }
148
148
149 public bool IsResolved {
149 public bool IsResolved {
150 get {
150 get {
151 Thread.MemoryBarrier();
151 return m_state > 1;
152 return m_state > 1;
152 }
153 }
153 }
154 }
154
155
155 public bool IsCancelled {
156 public bool IsCancelled {
156 get {
157 get {
158 Thread.MemoryBarrier();
157 return m_state == CANCELLED_STATE;
159 return m_state == CANCELLED_STATE;
158 }
160 }
159 }
161 }
160
162
161 public Type PromiseType {
163 public Type PromiseType {
162 get { return typeof(T); }
164 get { return typeof(T); }
163 }
165 }
164
166
165 /// <summary>
167 /// <summary>
166 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ.
168 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ.
167 /// </summary>
169 /// </summary>
168 /// <param name="result">Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния.</param>
170 /// <param name="result">Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния.</param>
169 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
171 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
170 public void Resolve(T result) {
172 public void Resolve(T result) {
171 if (BeginTransit()) {
173 if (BeginTransit()) {
172 m_result = result;
174 m_result = result;
173 CompleteTransit(SUCCEEDED_STATE);
175 CompleteTransit(SUCCEEDED_STATE);
174 OnStateChanged();
176 OnStateChanged();
175 } else {
177 } else {
176 WaitTransition();
178 WaitTransition();
177 if (m_state != CANCELLED_STATE)
179 if (m_state != CANCELLED_STATE)
178 throw new InvalidOperationException("The promise is already resolved");
180 throw new InvalidOperationException("The promise is already resolved");
179 }
181 }
180 }
182 }
181
183
182 /// <summary>
184 /// <summary>
183 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ. Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ выполнСния Π±ΡƒΠ΄Π΅Ρ‚ пустоС значСния.
185 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ. Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ выполнСния Π±ΡƒΠ΄Π΅Ρ‚ пустоС значСния.
184 /// </summary>
186 /// </summary>
185 /// <remarks>
187 /// <remarks>
186 /// Π”Π°Π½Π½Ρ‹ΠΉ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ ΡƒΠ΄ΠΎΠ±Π΅Π½ Π² случаях, ΠΊΠΎΠ³Π΄Π° интСрСсСн Ρ„Π°ΠΊΡ‚ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, Π½Π΅ΠΆΠ΅Π»ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.
188 /// Π”Π°Π½Π½Ρ‹ΠΉ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ ΡƒΠ΄ΠΎΠ±Π΅Π½ Π² случаях, ΠΊΠΎΠ³Π΄Π° интСрСсСн Ρ„Π°ΠΊΡ‚ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, Π½Π΅ΠΆΠ΅Π»ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.
187 /// </remarks>
189 /// </remarks>
188 public void Resolve() {
190 public void Resolve() {
189 Resolve(default(T));
191 Resolve(default(T));
190 }
192 }
191
193
192 /// <summary>
194 /// <summary>
193 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ошибкС
195 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ошибкС
194 /// </summary>
196 /// </summary>
195 /// <remarks>
197 /// <remarks>
196 /// ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС, ΠΏΡ€ΠΈ Π΅Π³ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ сразу нСсколько ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²
198 /// ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС, ΠΏΡ€ΠΈ Π΅Π³ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ сразу нСсколько ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²
197 /// ΠΌΠΎΠ³Ρƒ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ, ΠΏΡ€ΠΈ этом Ρ‚ΠΎΠ»ΡŒΠΊΠΎ пСрвая Π±ΡƒΠ΄Π΅Ρ‚ использована Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅
199 /// ΠΌΠΎΠ³Ρƒ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ, ΠΏΡ€ΠΈ этом Ρ‚ΠΎΠ»ΡŒΠΊΠΎ пСрвая Π±ΡƒΠ΄Π΅Ρ‚ использована Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅
198 /// Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΡ€ΠΎΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹.
200 /// Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΡ€ΠΎΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹.
199 /// </remarks>
201 /// </remarks>
200 /// <param name="error">Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ</param>
202 /// <param name="error">Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ</param>
201 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
203 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
202 public void Reject(Exception error) {
204 public void Reject(Exception error) {
203 if (BeginTransit()) {
205 if (BeginTransit()) {
204 m_error = error;
206 m_error = error;
205 CompleteTransit(REJECTED_STATE);
207 CompleteTransit(REJECTED_STATE);
206 OnStateChanged();
208 OnStateChanged();
207 } else {
209 } else {
208 WaitTransition();
210 WaitTransition();
209 if (m_state == SUCCEEDED_STATE)
211 if (m_state == SUCCEEDED_STATE)
210 throw new InvalidOperationException("The promise is already resolved");
212 throw new InvalidOperationException("The promise is already resolved");
211 }
213 }
212 }
214 }
213
215
214 /// <summary>
216 /// <summary>
215 /// ΠžΡ‚ΠΌΠ΅Π½ΡΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.
217 /// ΠžΡ‚ΠΌΠ΅Π½ΡΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.
216 /// </summary>
218 /// </summary>
217 /// <remarks>Для опрСдСлСния Π±Ρ‹Π»Π° Π»ΠΈ опСрация ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Π° слСдуСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ свойство <see cref="IsCancelled"/>.</remarks>
219 /// <remarks>Для опрСдСлСния Π±Ρ‹Π»Π° Π»ΠΈ опСрация ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Π° слСдуСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ свойство <see cref="IsCancelled"/>.</remarks>
218 public void Cancel() {
220 public void Cancel() {
219 if (m_cancellable && BeginTransit()) {
221 if (m_cancellable && BeginTransit()) {
220 CompleteTransit(CANCELLED_STATE);
222 CompleteTransit(CANCELLED_STATE);
221 OnStateChanged();
223 OnStateChanged();
222 }
224 }
223 }
225 }
224
226
225 public IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error, Action cancel) {
227 public IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error, Action cancel) {
226 if (success == null && error == null && cancel == null)
228 if (success == null && error == null && cancel == null)
227 return this;
229 return this;
228
230
229 var medium = new Promise<T>(this, true);
231 var medium = new Promise<T>(this, true);
230
232
231 AddHandler(success, error, cancel, medium);
233 AddHandler(success, error, cancel, medium);
232
234
233 return medium;
235 return medium;
234 }
236 }
235
237
236 /// <summary>
238 /// <summary>
237 /// Adds new handlers to this promise.
239 /// Adds new handlers to this promise.
238 /// </summary>
240 /// </summary>
239 /// <param name="success">The handler of the successfully completed operation.
241 /// <param name="success">The handler of the successfully completed operation.
240 /// This handler will recieve an operation result as a parameter.</param>
242 /// This handler will recieve an operation result as a parameter.</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>
243 /// <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>
242 /// <returns>The new promise chained to this one.</returns>
244 /// <returns>The new promise chained to this one.</returns>
243 public IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error) {
245 public IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error) {
244 if (success == null && error == null)
246 if (success == null && error == null)
245 return this;
247 return this;
246
248
247 var medium = new Promise<T>(this, true);
249 var medium = new Promise<T>(this, true);
248
250
249 AddHandler(success, error, null, medium);
251 AddHandler(success, error, null, medium);
250
252
251 return medium;
253 return medium;
252 }
254 }
253
255
254
256
255
257
256
258
257 public IPromise<T> Then(ResultHandler<T> success) {
259 public IPromise<T> Then(ResultHandler<T> success) {
258 if (success == null)
260 if (success == null)
259 return this;
261 return this;
260
262
261 var medium = new Promise<T>(this, true);
263 var medium = new Promise<T>(this, true);
262
264
263 AddHandler(success, null, null, medium);
265 AddHandler(success, null, null, medium);
264
266
265 return medium;
267 return medium;
266 }
268 }
267
269
268 /// <summary>
270 /// <summary>
269 /// ПослСдний ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
271 /// ПослСдний ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
270 /// </summary>
272 /// </summary>
271 /// <param name="success"></param>
273 /// <param name="success"></param>
272 /// <param name="error"></param>
274 /// <param name="error"></param>
273 /// <param name="cancel"></param>
275 /// <param name="cancel"></param>
274 /// <remarks>
276 /// <remarks>
275 /// <para>
277 /// <para>
276 /// Π”Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π½Π΅ создаСт связанного с Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΌ обСщания ΠΈ ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½ для окончания
278 /// Π”Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π½Π΅ создаСт связанного с Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΌ обСщания ΠΈ ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½ для окончания
277 /// фсинхронной Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ.
279 /// фсинхронной Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ.
278 /// </para>
280 /// </para>
279 /// <para>
281 /// <para>
280 /// Если Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ нСсколько Ρ€Π°Π·, Π»ΠΈΠ±ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, Ρ‚ΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ°
282 /// Если Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ нСсколько Ρ€Π°Π·, Π»ΠΈΠ±ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, Ρ‚ΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ°
281 /// Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ΄ΠΈΠ½ΠΎΡ‡Π½ΠΎΠΉ <see cref="IsExclusive"/> ΠΈ, ΠΊΠ°ΠΊ слСдствиС, Π±ΡƒΠ΄Π΅Ρ‚ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π° ΠΎΡ‚ΠΌΠ΅Π½Π°
283 /// Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ΄ΠΈΠ½ΠΎΡ‡Π½ΠΎΠΉ <see cref="IsExclusive"/> ΠΈ, ΠΊΠ°ΠΊ слСдствиС, Π±ΡƒΠ΄Π΅Ρ‚ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π° ΠΎΡ‚ΠΌΠ΅Π½Π°
282 /// всСй Ρ†Π΅ΠΏΠΈ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ снизу (с самого послСднСго обСщания).
284 /// всСй Ρ†Π΅ΠΏΠΈ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ снизу (с самого послСднСго обСщания).
283 /// </para>
285 /// </para>
284 /// </remarks>
286 /// </remarks>
285 public void Last(ResultHandler<T> success, ErrorHandler error, Action cancel) {
287 public void Last(ResultHandler<T> success, ErrorHandler error, Action cancel) {
286 if (success == null && error == null && cancel == null)
288 if (success == null && error == null && cancel == null)
287 return;
289 return;
288
290
289 ErrorHandler<T> errorHandler = null;
291 ErrorHandler<T> errorHandler = null;
290 if (error != null)
292 if (error != null)
291 errorHandler = err => {
293 errorHandler = err => {
292 error(err);
294 error(err);
293 return default(T);
295 return default(T);
294 };
296 };
295 AddHandler(success, errorHandler, cancel, null);
297 AddHandler(success, errorHandler, cancel, null);
296 }
298 }
297
299
298 public void Last(ResultHandler<T> success, ErrorHandler error) {
300 public void Last(ResultHandler<T> success, ErrorHandler error) {
299 Last(success, error, null);
301 Last(success, error, null);
300 }
302 }
301
303
302 public void Last(ResultHandler<T> success) {
304 public void Last(ResultHandler<T> success) {
303 Last(success, null, null);
305 Last(success, null, null);
304 }
306 }
305
307
306 public IPromise Error(ErrorHandler error) {
308 public IPromise Error(ErrorHandler error) {
307 if (error == null)
309 if (error == null)
308 return this;
310 return this;
309
311
310 var medium = new Promise<T>(this, true);
312 var medium = new Promise<T>(this, true);
311
313
312 AddHandler(
314 AddHandler(
313 null,
315 null,
314 e => {
316 e => {
315 error(e);
317 error(e);
316 return default(T);
318 return default(T);
317 },
319 },
318 null,
320 null,
319 medium
321 medium
320 );
322 );
321
323
322 return medium;
324 return medium;
323 }
325 }
324
326
325 /// <summary>
327 /// <summary>
326 /// Handles error and allows to keep the promise.
328 /// Handles error and allows to keep the promise.
327 /// </summary>
329 /// </summary>
328 /// <remarks>
330 /// <remarks>
329 /// If the specified handler throws an exception, this exception will be used to reject the promise.
331 /// If the specified handler throws an exception, this exception will be used to reject the promise.
330 /// </remarks>
332 /// </remarks>
331 /// <param name="handler">The error handler which returns the result of the promise.</param>
333 /// <param name="handler">The error handler which returns the result of the promise.</param>
332 /// <returns>New promise.</returns>
334 /// <returns>New promise.</returns>
333 public IPromise<T> Error(ErrorHandler<T> handler) {
335 public IPromise<T> Error(ErrorHandler<T> handler) {
334 if (handler == null)
336 if (handler == null)
335 return this;
337 return this;
336
338
337 var medium = new Promise<T>(this, true);
339 var medium = new Promise<T>(this, true);
338
340
339 AddHandler(null, handler, null, medium);
341 AddHandler(null, handler, null, medium);
340
342
341 return medium;
343 return medium;
342 }
344 }
343
345
344 /// <summary>
346 /// <summary>
345 /// ΠŸΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ‚ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.
347 /// ΠŸΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ‚ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.
346 /// </summary>
348 /// </summary>
347 /// <typeparam name="TNew">Новый Ρ‚ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°.</typeparam>
349 /// <typeparam name="TNew">Новый Ρ‚ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°.</typeparam>
348 /// <param name="mapper">ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.</param>
350 /// <param name="mapper">ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.</param>
349 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
351 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
350 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
352 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
351 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ исходного обСщания.</returns>
353 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ исходного обСщания.</returns>
352 public IPromise<TNew> Then<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler<TNew> error, Action cancel) {
354 public IPromise<TNew> Then<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler<TNew> error, Action cancel) {
353 Safe.ArgumentNotNull(mapper, "mapper");
355 Safe.ArgumentNotNull(mapper, "mapper");
354
356
355 // создаСм ΠΏΡ€ΠΈΡ†Π΅ΠΏΠ»Π΅Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
357 // создаСм ΠΏΡ€ΠΈΡ†Π΅ΠΏΠ»Π΅Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
356 var medium = new Promise<TNew>(this, true);
358 var medium = new Promise<TNew>(this, true);
357
359
358 ResultHandler<T> resultHandler = result => medium.Resolve(mapper(result));
360 ResultHandler<T> resultHandler = result => medium.Resolve(mapper(result));
359 ErrorHandler<T> errorHandler;
361 ErrorHandler<T> errorHandler;
360 if (error != null)
362 if (error != null)
361 errorHandler = e => {
363 errorHandler = e => {
362 try {
364 try {
363 medium.Resolve(error(e));
365 medium.Resolve(error(e));
364 } catch (Exception e2) {
366 } catch (Exception e2) {
365 // Π² случаС ошибки Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅
367 // Π² случаС ошибки Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅
366 medium.Reject(e2);
368 medium.Reject(e2);
367 }
369 }
368 return default(T);
370 return default(T);
369 };
371 };
370 else
372 else
371 errorHandler = e => {
373 errorHandler = e => {
372 medium.Reject(e);
374 medium.Reject(e);
373 return default(T);
375 return default(T);
374 };
376 };
375
377
376 Action cancelHandler;
378 Action cancelHandler;
377 if (cancel != null)
379 if (cancel != null)
378 cancelHandler = () => {
380 cancelHandler = () => {
379 cancel();
381 cancel();
380 medium.Cancel();
382 medium.Cancel();
381 };
383 };
382 else
384 else
383 cancelHandler = medium.Cancel;
385 cancelHandler = medium.Cancel;
384
386
385
387
386 AddHandler(
388 AddHandler(
387 resultHandler,
389 resultHandler,
388 errorHandler,
390 errorHandler,
389 cancelHandler,
391 cancelHandler,
390 null
392 null
391 );
393 );
392
394
393 return medium;
395 return medium;
394 }
396 }
395
397
396 public IPromise<TNew> Then<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler<TNew> error) {
398 public IPromise<TNew> Then<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler<TNew> error) {
397 return Then(mapper, error, null);
399 return Then(mapper, error, null);
398 }
400 }
399
401
400 public IPromise<TNew> Then<TNew>(ResultMapper<T, TNew> mapper) {
402 public IPromise<TNew> Then<TNew>(ResultMapper<T, TNew> mapper) {
401 return Then(mapper, null, null);
403 return Then(mapper, null, null);
402 }
404 }
403
405
404 /// <summary>
406 /// <summary>
405 /// БцСпляСт нСсколько аснхронных ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ. Указанная асинхронная опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½Π° послС
407 /// БцСпляСт нСсколько аснхронных ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ. Указанная асинхронная опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½Π° послС
406 /// выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ, Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ использован для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ
408 /// выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ, Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ использован для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ
407 /// Π½ΠΎΠ²ΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.
409 /// Π½ΠΎΠ²ΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.
408 /// </summary>
410 /// </summary>
409 /// <typeparam name="TNew">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</typeparam>
411 /// <typeparam name="TNew">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</typeparam>
410 /// <param name="chained">Асинхронная опСрация, которая Π΄ΠΎΠ»ΠΆΠ½Π° Π±ΡƒΠ΄Π΅Ρ‚ Π½Π°Ρ‡Π°Ρ‚ΡŒΡΡ послС выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ.</param>
412 /// <param name="chained">Асинхронная опСрация, которая Π΄ΠΎΠ»ΠΆΠ½Π° Π±ΡƒΠ΄Π΅Ρ‚ Π½Π°Ρ‡Π°Ρ‚ΡŒΡΡ послС выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ.</param>
411 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
413 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
412 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Ρ‚Π΅ΠΊΡƒΠ΅Ρ‰ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
414 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Ρ‚Π΅ΠΊΡƒΠ΅Ρ‰ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
413 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ аснхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</returns>
415 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ аснхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</returns>
414 public IPromise<TNew> Chain<TNew>(ResultMapper<T, IPromise<TNew>> chained, ErrorHandler<IPromise<TNew>> error, Action cancel) {
416 public IPromise<TNew> Chain<TNew>(ResultMapper<T, IPromise<TNew>> chained, ErrorHandler<IPromise<TNew>> error, Action cancel) {
415
417
416 Safe.ArgumentNotNull(chained, "chained");
418 Safe.ArgumentNotNull(chained, "chained");
417
419
418 // ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ‚ связывания Π΅Ρ‰Π΅ Π½Π΅ Π½Π°Ρ‡Π°Ρ‚Π° асинхронная опСрация, поэтому Π½ΡƒΠΆΠ½ΠΎ
420 // ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ‚ связывания Π΅Ρ‰Π΅ Π½Π΅ Π½Π°Ρ‡Π°Ρ‚Π° асинхронная опСрация, поэтому Π½ΡƒΠΆΠ½ΠΎ
419 // ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ посрСдника, ΠΊ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠΎΠ΄Π²Ρ‹Π·ΡΠ²Π°Ρ‚ΡŒΡΡ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ.
421 // ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ посрСдника, ΠΊ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠΎΠ΄Π²Ρ‹Π·ΡΠ²Π°Ρ‚ΡŒΡΡ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ.
420 // ΠΊΠΎΠ³Π΄Π° Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° Ρ€Π΅Π°Π»ΡŒΠ½Π°Ρ асинхронная опСрация, ΠΎΠ½Π° ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ ΠΊ посрСднику, Ρ‡Ρ‚ΠΎΠ±Ρ‹
422 // ΠΊΠΎΠ³Π΄Π° Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° Ρ€Π΅Π°Π»ΡŒΠ½Π°Ρ асинхронная опСрация, ΠΎΠ½Π° ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ ΠΊ посрСднику, Ρ‡Ρ‚ΠΎΠ±Ρ‹
421 // ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· Π½Π΅Π³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Ρ€Π°Π±ΠΎΡ‚Ρ‹.
423 // ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· Π½Π΅Π³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Ρ€Π°Π±ΠΎΡ‚Ρ‹.
422 var medium = new Promise<TNew>(this, true);
424 var medium = new Promise<TNew>(this, true);
423
425
424 ResultHandler<T> resultHandler = delegate(T result) {
426 ResultHandler<T> resultHandler = delegate(T result) {
425 if (medium.IsCancelled)
427 if (medium.IsCancelled)
426 return;
428 return;
427
429
428 var promise = chained(result);
430 var promise = chained(result);
429
431
430 promise.Last(
432 promise.Last(
431 medium.Resolve,
433 medium.Resolve,
432 medium.Reject,
434 medium.Reject,
433 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
435 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
434 );
436 );
435
437
436 // notify chained operation that it's not needed anymore
438 // notify chained operation that it's not needed anymore
437 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
439 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
438 // зависит IsExclusive
440 // зависит IsExclusive
439 medium.Cancelled(() => {
441 medium.Cancelled(() => {
440 if (promise.IsExclusive)
442 if (promise.IsExclusive)
441 promise.Cancel();
443 promise.Cancel();
442 });
444 });
443 };
445 };
444
446
445 ErrorHandler<T> errorHandler;
447 ErrorHandler<T> errorHandler;
446
448
447 if (error != null)
449 if (error != null)
448 errorHandler = delegate(Exception e) {
450 errorHandler = delegate(Exception e) {
449 try {
451 try {
450 var promise = error(e);
452 var promise = error(e);
451
453
452 promise.Last(
454 promise.Last(
453 medium.Resolve,
455 medium.Resolve,
454 medium.Reject,
456 medium.Reject,
455 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
457 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
456 );
458 );
457
459
458 // notify chained operation that it's not needed anymore
460 // notify chained operation that it's not needed anymore
459 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
461 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
460 // зависит IsExclusive
462 // зависит IsExclusive
461 medium.Cancelled(() => {
463 medium.Cancelled(() => {
462 if (promise.IsExclusive)
464 if (promise.IsExclusive)
463 promise.Cancel();
465 promise.Cancel();
464 });
466 });
465 } catch (Exception e2) {
467 } catch (Exception e2) {
466 medium.Reject(e2);
468 medium.Reject(e2);
467 }
469 }
468 return default(T);
470 return default(T);
469 };
471 };
470 else
472 else
471 errorHandler = err => {
473 errorHandler = err => {
472 medium.Reject(err);
474 medium.Reject(err);
473 return default(T);
475 return default(T);
474 };
476 };
475
477
476
478
477 Action cancelHandler;
479 Action cancelHandler;
478 if (cancel != null)
480 if (cancel != null)
479 cancelHandler = () => {
481 cancelHandler = () => {
480 if (cancel != null)
482 if (cancel != null)
481 cancel();
483 cancel();
482 medium.Cancel();
484 medium.Cancel();
483 };
485 };
484 else
486 else
485 cancelHandler = medium.Cancel;
487 cancelHandler = medium.Cancel;
486
488
487 AddHandler(
489 AddHandler(
488 resultHandler,
490 resultHandler,
489 errorHandler,
491 errorHandler,
490 cancelHandler,
492 cancelHandler,
491 null
493 null
492 );
494 );
493
495
494 return medium;
496 return medium;
495 }
497 }
496
498
497 public IPromise<TNew> Chain<TNew>(ResultMapper<T, IPromise<TNew>> chained, ErrorHandler<IPromise<TNew>> error) {
499 public IPromise<TNew> Chain<TNew>(ResultMapper<T, IPromise<TNew>> chained, ErrorHandler<IPromise<TNew>> error) {
498 return Chain(chained, error, null);
500 return Chain(chained, error, null);
499 }
501 }
500
502
501 public IPromise<TNew> Chain<TNew>(ResultMapper<T, IPromise<TNew>> chained) {
503 public IPromise<TNew> Chain<TNew>(ResultMapper<T, IPromise<TNew>> chained) {
502 return Chain(chained, null, null);
504 return Chain(chained, null, null);
503 }
505 }
504
506
505 public IPromise<T> Cancelled(Action handler) {
507 public IPromise<T> Cancelled(Action handler) {
506 var medium = new Promise<T>(this,true);
508 var medium = new Promise<T>(this,true);
507 AddHandler(null, null, handler, medium);
509 AddHandler(null, null, handler, medium);
508 return medium;
510 return medium;
509 }
511 }
510
512
511 /// <summary>
513 /// <summary>
512 /// Adds the specified handler for all cases (success, error, cancel)
514 /// Adds the specified handler for all cases (success, error, cancel)
513 /// </summary>
515 /// </summary>
514 /// <param name="handler">The handler that will be called anyway</param>
516 /// <param name="handler">The handler that will be called anyway</param>
515 /// <returns>self</returns>
517 /// <returns>self</returns>
516 public IPromise<T> Anyway(Action handler) {
518 public IPromise<T> Anyway(Action handler) {
517 Safe.ArgumentNotNull(handler, "handler");
519 Safe.ArgumentNotNull(handler, "handler");
518
520
519 AddHandler(
521 AddHandler(
520 x => handler(),
522 x => handler(),
521 e => {
523 e => {
522 handler();
524 handler();
523 throw new TransientPromiseException(e);
525 throw new TransientPromiseException(e);
524 },
526 },
525 handler,
527 handler,
526 null
528 null
527 );
529 );
528 return this;
530 return this;
529 }
531 }
530
532
531 /// <summary>
533 /// <summary>
532 /// ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ обСщания ΠΊ Π½ΡƒΠΆΠ½ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ
534 /// ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ обСщания ΠΊ Π½ΡƒΠΆΠ½ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ
533 /// </summary>
535 /// </summary>
534 /// <typeparam name="T2"></typeparam>
536 /// <typeparam name="T2"></typeparam>
535 /// <returns></returns>
537 /// <returns></returns>
536 public IPromise<T2> Cast<T2>() {
538 public IPromise<T2> Cast<T2>() {
537 return Then(x => (T2)(object)x, null);
539 return Then(x => (T2)(object)x, null);
538 }
540 }
539
541
540 /// <summary>
542 /// <summary>
541 /// ДоТидаСтся ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ³ΠΎ обСщания ΠΈ Π² случаС успСха, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚
543 /// ДоТидаСтся ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ³ΠΎ обСщания ΠΈ Π² случаС успСха, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚
542 /// Π΅Π³ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС бросаСт ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.
544 /// Π΅Π³ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС бросаСт ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.
543 /// </summary>
545 /// </summary>
544 /// <remarks>
546 /// <remarks>
545 /// <para>
547 /// <para>
546 /// Если ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ обСщания Π±Ρ‹Π»ΠΎ ΠΏΡ€Π΅Ρ€Π²Π°Π½ΠΎ ΠΏΠΎ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚Ρƒ, это Π½Π΅ Π·Π½Π°Ρ‡ΠΈΡ‚,
548 /// Если ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ обСщания Π±Ρ‹Π»ΠΎ ΠΏΡ€Π΅Ρ€Π²Π°Π½ΠΎ ΠΏΠΎ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚Ρƒ, это Π½Π΅ Π·Π½Π°Ρ‡ΠΈΡ‚,
547 /// Ρ‡Ρ‚ΠΎ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±Ρ‹Π»ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½ΠΎ ΠΈΠ»ΠΈ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π² этом Ρ€ΠΎΠ΄Π΅, это Ρ‚ΠΎΠ»ΡŒΠΊΠΎ
549 /// Ρ‡Ρ‚ΠΎ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±Ρ‹Π»ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½ΠΎ ΠΈΠ»ΠΈ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π² этом Ρ€ΠΎΠ΄Π΅, это Ρ‚ΠΎΠ»ΡŒΠΊΠΎ
548 /// ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π΅Π³ΠΎ Π½Π΅ доТдались, ΠΎΠ΄Π½Π°ΠΊΠΎ всС зарСгистрированныС
550 /// ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π΅Π³ΠΎ Π½Π΅ доТдались, ΠΎΠ΄Π½Π°ΠΊΠΎ всС зарСгистрированныС
549 /// ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, ΠΊΠ°ΠΊ Π±Ρ‹Π»ΠΈ Ρ‚Π°ΠΊ ΠΎΡΡ‚Π°Π»ΠΈΡΡŒ ΠΈ ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹, ΠΊΠΎΠ³Π΄Π°
551 /// ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, ΠΊΠ°ΠΊ Π±Ρ‹Π»ΠΈ Ρ‚Π°ΠΊ ΠΎΡΡ‚Π°Π»ΠΈΡΡŒ ΠΈ ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹, ΠΊΠΎΠ³Π΄Π°
550 /// ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
552 /// ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
551 /// </para>
553 /// </para>
552 /// <para>
554 /// <para>
553 /// Π’Π°ΠΊΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π²ΠΏΠΎΠ»Π½Π΅ ΠΎΠΏΡ€Π°Π²Π΄Π°Π½ΠΎ ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΡ‚Π΅Ρ‡ΡŒ
555 /// Π’Π°ΠΊΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π²ΠΏΠΎΠ»Π½Π΅ ΠΎΠΏΡ€Π°Π²Π΄Π°Π½ΠΎ ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΡ‚Π΅Ρ‡ΡŒ
554 /// Π² Ρ‚ΠΎΡ‚ ΠΌΠΎΠΌΠ΅Π½Ρ‚, ΠΊΠΎΠ³Π΄Π° Π½Π°Ρ‡Π°Π»Π°ΡΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ², ΠΈ
556 /// Π² Ρ‚ΠΎΡ‚ ΠΌΠΎΠΌΠ΅Π½Ρ‚, ΠΊΠΎΠ³Π΄Π° Π½Π°Ρ‡Π°Π»Π°ΡΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ², ΠΈ
555 /// ΠΊ Ρ‚ΠΎΠΌΡƒ ΠΆΠ΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡ‚ΠΎΡΡ‚ΡŒ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ ΠΈ Π΅Π³ΠΎ
557 /// ΠΊ Ρ‚ΠΎΠΌΡƒ ΠΆΠ΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡ‚ΠΎΡΡ‚ΡŒ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ ΠΈ Π΅Π³ΠΎ
556 /// ΠΎΡ‚ΠΊΠ»ΠΎΠ½Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ Π½Π΅ΠΏΡ€ΠΎΠ³Π½ΠΎΠ·ΠΈΡ€ΡƒΠ΅ΠΌΠΎΠΌΡƒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρƒ.
558 /// ΠΎΡ‚ΠΊΠ»ΠΎΠ½Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ Π½Π΅ΠΏΡ€ΠΎΠ³Π½ΠΎΠ·ΠΈΡ€ΡƒΠ΅ΠΌΠΎΠΌΡƒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρƒ.
557 /// </para>
559 /// </para>
558 /// </remarks>
560 /// </remarks>
559 /// <param name="timeout">ВрСмя оТидания</param>
561 /// <param name="timeout">ВрСмя оТидания</param>
560 /// <returns>Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния обСщания</returns>
562 /// <returns>Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния обСщания</returns>
561 public T Join(int timeout) {
563 public T Join(int timeout) {
562 var evt = new ManualResetEvent(false);
564 var evt = new ManualResetEvent(false);
563 Anyway(() => evt.Set());
565 Anyway(() => evt.Set());
564
566
565 if (!evt.WaitOne(timeout, true))
567 if (!evt.WaitOne(timeout, true))
566 throw new TimeoutException();
568 throw new TimeoutException();
567
569
568 switch (m_state) {
570 switch (m_state) {
569 case SUCCEEDED_STATE:
571 case SUCCEEDED_STATE:
570 return m_result;
572 return m_result;
571 case CANCELLED_STATE:
573 case CANCELLED_STATE:
572 throw new OperationCanceledException();
574 throw new OperationCanceledException();
573 case REJECTED_STATE:
575 case REJECTED_STATE:
574 throw new TargetInvocationException(m_error);
576 throw new TargetInvocationException(m_error);
575 default:
577 default:
576 throw new ApplicationException(String.Format("Invalid promise state {0}", m_state));
578 throw new ApplicationException(String.Format("Invalid promise state {0}", m_state));
577 }
579 }
578 }
580 }
579
581
580 public T Join() {
582 public T Join() {
581 return Join(Timeout.Infinite);
583 return Join(Timeout.Infinite);
582 }
584 }
583
585
584 void AddHandler(ResultHandler<T> success, ErrorHandler<T> error, Action cancel, Promise<T> medium) {
586 void AddHandler(ResultHandler<T> success, ErrorHandler<T> error, Action cancel, Promise<T> medium) {
585 if (success != null || error != null)
587 if (success != null || error != null)
586 Interlocked.Increment(ref m_childrenCount);
588 Interlocked.Increment(ref m_childrenCount);
587
589
588 var handler = new HandlerDescriptor {
590 var handler = new HandlerDescriptor {
589 resultHandler = success,
591 resultHandler = success,
590 errorHandler = error,
592 errorHandler = error,
591 cancellHandler = cancel,
593 cancellHandler = cancel,
592 medium = medium
594 medium = medium
593 };
595 };
594
596
595 bool queued;
597 bool queued;
596
598
597 if (!IsResolved) {
599 if (!IsResolved) {
598 m_handlers.Enqueue(handler);
600 m_handlers.Enqueue(handler);
599 queued = true;
601 queued = true;
600 } else {
602 } else {
601 // the promise is in resolved state, just invoke the handled with minimum overhead
603 // the promise is in resolved state, just invoke the handled with minimum overhead
602 queued = false;
604 queued = false;
603 InvokeHandler(handler);
605 InvokeHandler(handler);
604 }
606 }
605
607
606 if (queued && IsResolved && m_handlers.TryDequeue(out handler))
608 if (queued && IsResolved && m_handlers.TryDequeue(out handler))
607 // if the promise have been resolved while we was adding handler to the queue
609 // if the promise have been resolved while we was adding handler to the queue
608 // we can't guarantee that someone is still processing it
610 // we can't guarantee that someone is still processing it
609 // therefore we will fetch a handler from the queue and execute it
611 // therefore we will fetch a handler from the queue and execute it
610 // note that fetched handler may be not the one that we have added
612 // note that fetched handler may be not the one that we have added
611 // even we can fetch no handlers at all :)
613 // even we can fetch no handlers at all :)
612 InvokeHandler(handler);
614 InvokeHandler(handler);
613 }
615 }
614
616
615 protected virtual void InvokeHandler(HandlerDescriptor handler) {
617 protected virtual void InvokeHandler(HandlerDescriptor handler) {
616 switch (m_state) {
618 switch (m_state) {
617 case SUCCEEDED_STATE:
619 case SUCCEEDED_STATE:
618 handler.Resolve(m_result);
620 handler.Resolve(m_result);
619 break;
621 break;
620 case REJECTED_STATE:
622 case REJECTED_STATE:
621 handler.Reject(m_error);
623 handler.Reject(m_error);
622 break;
624 break;
623 case CANCELLED_STATE:
625 case CANCELLED_STATE:
624 handler.Cancel();
626 handler.Cancel();
625 break;
627 break;
626 default:
628 default:
627 // do nothing
629 // do nothing
628 return;
630 return;
629 }
631 }
630 }
632 }
631
633
632 void OnStateChanged() {
634 void OnStateChanged() {
633 HandlerDescriptor handler;
635 HandlerDescriptor handler;
634 while (m_handlers.TryDequeue(out handler))
636 while (m_handlers.TryDequeue(out handler))
635 InvokeHandler(handler);
637 InvokeHandler(handler);
636 }
638 }
637
639
638 public bool IsExclusive {
640 public bool IsExclusive {
639 get {
641 get {
640 return m_childrenCount <= 1;
642 return m_childrenCount <= 1;
641 }
643 }
642 }
644 }
643
645
644 /// <summary>
646 /// <summary>
645 /// ΠžΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ нСсколько ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ являСтся массив Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
647 /// ΠžΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ нСсколько ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ являСтся массив Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
646 /// Если хотябы ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚ΠΎ Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ Ρ‚ΠΎΠΆΠ΅ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
648 /// Если хотябы ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚ΠΎ Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ Ρ‚ΠΎΠΆΠ΅ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
647 /// ΠŸΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ Π½ΠΎΠ²ΠΎΠ³ΠΎ обСщания, ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅ обСщания Ρ‚Π°ΠΊΠΆΠ΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Ρ‹, Ссли Π½ΠΈΠΊΡ‚ΠΎ большС Π½Π° Π½ΠΈΡ… Π½Π΅ подписан.
649 /// ΠŸΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ Π½ΠΎΠ²ΠΎΠ³ΠΎ обСщания, ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅ обСщания Ρ‚Π°ΠΊΠΆΠ΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Ρ‹, Ссли Π½ΠΈΠΊΡ‚ΠΎ большС Π½Π° Π½ΠΈΡ… Π½Π΅ подписан.
648 /// </summary>
650 /// </summary>
649 /// <param name="promises">Бписок ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ. Если список пустой, Ρ‚ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ возвращаСтся ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹ΠΌ.</param>
651 /// <param name="promises">Бписок ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ. Если список пустой, Ρ‚ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ возвращаСтся ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹ΠΌ.</param>
650 /// <returns>ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰Π΅Π΅ Π² сСбС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.</returns>
652 /// <returns>ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰Π΅Π΅ Π² сСбС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.</returns>
651 /// <exception cref="ArgumentNullException"><paramref name="promises"/> Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ null</exception>
653 /// <exception cref="ArgumentNullException"><paramref name="promises"/> Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ null</exception>
652 public static IPromise<T[]> CreateComposite(IList<IPromise<T>> promises) {
654 public static IPromise<T[]> CreateComposite(IList<IPromise<T>> promises) {
653 if (promises == null)
655 if (promises == null)
654 throw new ArgumentNullException();
656 throw new ArgumentNullException();
655
657
656 // создаСм аккумулятор для Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² ΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
658 // создаСм аккумулятор для Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² ΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
657 var result = new T[promises.Count];
659 var result = new T[promises.Count];
658 var promise = new Promise<T[]>();
660 var promise = new Promise<T[]>();
659
661
660 // special case
662 // special case
661 if (promises.Count == 0) {
663 if (promises.Count == 0) {
662 promise.Resolve(result);
664 promise.Resolve(result);
663 return promise;
665 return promise;
664 }
666 }
665
667
666 int pending = promises.Count;
668 int pending = promises.Count;
667
669
668 for (int i = 0; i < promises.Count; i++) {
670 for (int i = 0; i < promises.Count; i++) {
669 var dest = i;
671 var dest = i;
670
672
671 if (promises[i] != null) {
673 if (promises[i] != null) {
672 promises[i].Then(
674 promises[i].Then(
673 x => {
675 x => {
674 result[dest] = x;
676 result[dest] = x;
675 if (Interlocked.Decrement(ref pending) == 0)
677 if (Interlocked.Decrement(ref pending) == 0)
676 promise.Resolve(result);
678 promise.Resolve(result);
677 },
679 },
678 e => {
680 e => {
679 promise.Reject(e);
681 promise.Reject(e);
680 return default(T);
682 return default(T);
681 }
683 }
682 );
684 );
683 } else {
685 } else {
684 if (Interlocked.Decrement(ref pending) == 0)
686 if (Interlocked.Decrement(ref pending) == 0)
685 promise.Resolve(result);
687 promise.Resolve(result);
686 }
688 }
687 }
689 }
688
690
689 promise.Cancelled(
691 promise.Cancelled(
690 () => {
692 () => {
691 foreach (var d in promises)
693 foreach (var d in promises)
692 if (d != null && d.IsExclusive)
694 if (d != null && d.IsExclusive)
693 d.Cancel();
695 d.Cancel();
694 }
696 }
695 );
697 );
696
698
697 return promise;
699 return promise;
698 }
700 }
699
701
700 /// <summary>
702 /// <summary>
701 /// ΠžΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ нСсколько ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ. Π Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ
703 /// ΠžΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ нСсколько ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ. Π Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ
702 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ всСх ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ. ΠŸΡ€ΠΈ этом Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹Π΅ значСния ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ
704 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ всСх ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ. ΠŸΡ€ΠΈ этом Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹Π΅ значСния ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ
703 /// ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΡƒΡŽΡ‚ΡΡ.
705 /// ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΡƒΡŽΡ‚ΡΡ.
704 /// </summary>
706 /// </summary>
705 /// <param name="promises">ΠšΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΡ ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΠ±ΡŠΠ΅Π΄Π΅Π½Π΅Π½Ρ‹ Π² ΠΎΠ΄Π½ΠΎ.</param>
707 /// <param name="promises">ΠšΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΡ ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΠ±ΡŠΠ΅Π΄Π΅Π½Π΅Π½Ρ‹ Π² ΠΎΠ΄Π½ΠΎ.</param>
706 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰Π΅Π΅ Π² сСбС ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅.</returns>
708 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰Π΅Π΅ Π² сСбС ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅.</returns>
707 /// <remarks>
709 /// <remarks>
708 /// Если Π² ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΈ Π²ΡΡ‚Ρ€Π΅Ρ‡Π°ΡŽΡŒΡΡ <c>null</c>, Ρ‚ΠΎ ΠΎΠ½ΠΈ Π²ΠΎΡΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹Π΅ обСщания.
710 /// Если Π² ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΈ Π²ΡΡ‚Ρ€Π΅Ρ‡Π°ΡŽΡŒΡΡ <c>null</c>, Ρ‚ΠΎ ΠΎΠ½ΠΈ Π²ΠΎΡΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹Π΅ обСщания.
709 /// </remarks>
711 /// </remarks>
710 public static IPromise CreateComposite(ICollection<IPromise> promises) {
712 public static IPromise CreateComposite(ICollection<IPromise> promises) {
711 if (promises == null)
713 if (promises == null)
712 throw new ArgumentNullException();
714 throw new ArgumentNullException();
713 if (promises.Count == 0)
715 if (promises.Count == 0)
714 return Promise<object>.ResultToPromise(null);
716 return Promise<object>.ResultToPromise(null);
715
717
716 int countdown = promises.Count;
718 int countdown = promises.Count;
717
719
718 var result = new Promise<object>();
720 var result = new Promise<object>();
719
721
720 foreach (var d in promises) {
722 foreach (var d in promises) {
721 if (d == null) {
723 if (d == null) {
722 if (Interlocked.Decrement(ref countdown) == 0)
724 if (Interlocked.Decrement(ref countdown) == 0)
723 result.Resolve(null);
725 result.Resolve(null);
724 } else {
726 } else {
725 d.Then(() => {
727 d.Then(() => {
726 if (Interlocked.Decrement(ref countdown) == 0)
728 if (Interlocked.Decrement(ref countdown) == 0)
727 result.Resolve(null);
729 result.Resolve(null);
728 });
730 });
729 }
731 }
730 }
732 }
731
733
732 result.Cancelled(() => {
734 result.Cancelled(() => {
733 foreach (var d in promises)
735 foreach (var d in promises)
734 if (d != null && d.IsExclusive)
736 if (d != null && d.IsExclusive)
735 d.Cancel();
737 d.Cancel();
736 });
738 });
737
739
738 return result;
740 return result;
739 }
741 }
740
742
741 public static Promise<T> ResultToPromise(T result) {
743 public static Promise<T> ResultToPromise(T result) {
742 var p = new Promise<T>();
744 var p = new Promise<T>();
743 p.Resolve(result);
745 p.Resolve(result);
744 return p;
746 return p;
745 }
747 }
746
748
747 public static Promise<T> ExceptionToPromise(Exception error) {
749 public static Promise<T> ExceptionToPromise(Exception error) {
748 if (error == null)
750 if (error == null)
749 throw new ArgumentNullException();
751 throw new ArgumentNullException();
750
752
751 var p = new Promise<T>();
753 var p = new Promise<T>();
752 p.Reject(error);
754 p.Reject(error);
753 return p;
755 return p;
754 }
756 }
755
757
756 #region IPromiseBase explicit implementation
758 #region IPromiseBase explicit implementation
757
759
758 IPromise IPromise.Then(Action success, ErrorHandler error, Action cancel) {
760 IPromise IPromise.Then(Action success, ErrorHandler error, Action cancel) {
759 return Then(
761 return Then(
760 x => success(),
762 x => success(),
761 e => {
763 e => {
762 error(e);
764 error(e);
763 return default(T);
765 return default(T);
764 },
766 },
765 cancel
767 cancel
766 );
768 );
767 }
769 }
768
770
769 IPromise IPromise.Then(Action success, ErrorHandler error) {
771 IPromise IPromise.Then(Action success, ErrorHandler error) {
770 return Then(
772 return Then(
771 x => success(),
773 x => success(),
772 e => {
774 e => {
773 error(e);
775 error(e);
774 return default(T);
776 return default(T);
775 }
777 }
776 );
778 );
777 }
779 }
778
780
779 IPromise IPromise.Then(Action success) {
781 IPromise IPromise.Then(Action success) {
780 return Then(x => success());
782 return Then(x => success());
781 }
783 }
782
784
783 void IPromise.Last(Action success, ErrorHandler error, Action cancel) {
785 void IPromise.Last(Action success, ErrorHandler error, Action cancel) {
784 Last(x => success(), error, cancel);
786 Last(x => success(), error, cancel);
785 }
787 }
786
788
787 void IPromise.Last(Action success, ErrorHandler error) {
789 void IPromise.Last(Action success, ErrorHandler error) {
788 Last(x => success(), error, null);
790 Last(x => success(), error, null);
789 }
791 }
790
792
791 void IPromise.Last(Action success) {
793 void IPromise.Last(Action success) {
792 Last(x => success(), null, null);
794 Last(x => success(), null, null);
793 }
795 }
794
796
795 IPromise IPromise.Error(ErrorHandler error) {
797 IPromise IPromise.Error(ErrorHandler error) {
796 return Error(error);
798 return Error(error);
797 }
799 }
798
800
799 IPromise IPromise.Anyway(Action handler) {
801 IPromise IPromise.Anyway(Action handler) {
800 return Anyway(handler);
802 return Anyway(handler);
801 }
803 }
802
804
803 IPromise IPromise.Cancelled(Action handler) {
805 IPromise IPromise.Cancelled(Action handler) {
804 return Cancelled(handler);
806 return Cancelled(handler);
805 }
807 }
806
808
807 void IPromise.Join() {
809 void IPromise.Join() {
808 Join();
810 Join();
809 }
811 }
810
812
811 void IPromise.Join(int timeout) {
813 void IPromise.Join(int timeout) {
812 Join(timeout);
814 Join(timeout);
813 }
815 }
814
816
815 #endregion
817 #endregion
816
818
817
819
818
820
819 }
821 }
820 }
822 }
General Comments 0
You need to be logged in to leave comments. Login now