##// END OF EJS Templates
Implemented interllocked queue...
cin -
r14:e943453e5039 promises
parent child
Show More
@@ -0,0 +1,74
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading;
6
7 namespace Implab.Parallels {
8 public class MTQueue<T> {
9 class Node {
10 public Node(T value) {
11 this.value = value;
12 }
13 public readonly T value;
14 public Node next;
15 }
16
17 Node m_first;
18 Node m_last;
19
20 public void Enqueue(T value) {
21 var last = m_last;
22 var next = new Node(value);
23
24 while (last != Interlocked.CompareExchange(ref m_last, next, last))
25 last = m_last;
26
27 if (last != null)
28 last.next = next;
29 else
30 m_first = next;
31 }
32
33 public bool TryDequeue(out T value) {
34 Node first;
35 Node next = null;
36 value = default(T);
37
38 do {
39 first = m_first;
40 if (first == null)
41 return false;
42 next = first.next;
43 if (next == null) {
44 // this is the last element,
45 // then try to update tail
46 if (first != Interlocked.CompareExchange(ref m_last, null, first)) {
47 // this is inconsistent situation which means that the queue is empty
48 if (m_last == null)
49 return false;
50 // tail has been changed, that means that we need to restart
51 continue;
52 }
53
54 // tail succesfully updated and first.next will never be changed
55 // other readers will fail due to inconsistency m_last != m_fist, but m_first.next == null
56 // but the writer may update the m_first since the m_last is null
57
58 // so we need to fix inconsistency by setting m_first to null, but if it already has been
59 // updated by a writer then we should just give up
60 Interlocked.CompareExchange(ref m_first, null, first);
61 break;
62
63 } else {
64 if (first == Interlocked.CompareExchange(ref m_first, next, first))
65 // head succesfully updated
66 break;
67 }
68 } while (true);
69
70 value = first.value;
71 return true;
72 }
73 }
74 }
@@ -1,169 +1,240
1 using System;
1 using System;
2 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using Microsoft.VisualStudio.TestTools.UnitTesting;
3 using System.Reflection;
3 using System.Reflection;
4 using System.Threading;
4 using System.Threading;
5 using Implab.Parallels;
5 using Implab.Parallels;
6
6
7 namespace Implab.Test
7 namespace Implab.Test
8 {
8 {
9 [TestClass]
9 [TestClass]
10 public class AsyncTests
10 public class AsyncTests
11 {
11 {
12 [TestMethod]
12 [TestMethod]
13 public void ResolveTest ()
13 public void ResolveTest ()
14 {
14 {
15 int res = -1;
15 int res = -1;
16 var p = new Promise<int> ();
16 var p = new Promise<int> ();
17 p.Then (x => res = x);
17 p.Then (x => res = x);
18 p.Resolve (100);
18 p.Resolve (100);
19
19
20 Assert.AreEqual (res, 100);
20 Assert.AreEqual (res, 100);
21 }
21 }
22
22
23 [TestMethod]
23 [TestMethod]
24 public void RejectTest ()
24 public void RejectTest ()
25 {
25 {
26 int res = -1;
26 int res = -1;
27 Exception err = null;
27 Exception err = null;
28
28
29 var p = new Promise<int> ();
29 var p = new Promise<int> ();
30 p.Then (x => res = x, e => err = e);
30 p.Then (x => res = x, e => err = e);
31 p.Reject (new ApplicationException ("error"));
31 p.Reject (new ApplicationException ("error"));
32
32
33 Assert.AreEqual (res, -1);
33 Assert.AreEqual (res, -1);
34 Assert.AreEqual (err.Message, "error");
34 Assert.AreEqual (err.Message, "error");
35
35
36 }
36 }
37
37
38 [TestMethod]
38 [TestMethod]
39 public void JoinSuccessTest ()
39 public void JoinSuccessTest ()
40 {
40 {
41 var p = new Promise<int> ();
41 var p = new Promise<int> ();
42 p.Resolve (100);
42 p.Resolve (100);
43 Assert.AreEqual (p.Join (), 100);
43 Assert.AreEqual (p.Join (), 100);
44 }
44 }
45
45
46 [TestMethod]
46 [TestMethod]
47 public void JoinFailTest ()
47 public void JoinFailTest ()
48 {
48 {
49 var p = new Promise<int> ();
49 var p = new Promise<int> ();
50 p.Reject (new ApplicationException ("failed"));
50 p.Reject (new ApplicationException ("failed"));
51
51
52 try {
52 try {
53 p.Join ();
53 p.Join ();
54 throw new ApplicationException ("WRONG!");
54 throw new ApplicationException ("WRONG!");
55 } catch (TargetInvocationException err) {
55 } catch (TargetInvocationException err) {
56 Assert.AreEqual (err.InnerException.Message, "failed");
56 Assert.AreEqual (err.InnerException.Message, "failed");
57 } catch {
57 } catch {
58 Assert.Fail ("Got wrong excaption");
58 Assert.Fail ("Got wrong excaption");
59 }
59 }
60 }
60 }
61
61
62 [TestMethod]
62 [TestMethod]
63 public void MapTest ()
63 public void MapTest ()
64 {
64 {
65 var p = new Promise<int> ();
65 var p = new Promise<int> ();
66
66
67 var p2 = p.Map (x => x.ToString ());
67 var p2 = p.Map (x => x.ToString ());
68 p.Resolve (100);
68 p.Resolve (100);
69
69
70 Assert.AreEqual (p2.Join (), "100");
70 Assert.AreEqual (p2.Join (), "100");
71 }
71 }
72
72
73 [TestMethod]
73 [TestMethod]
74 public void FixErrorTest() {
74 public void FixErrorTest() {
75 var p = new Promise<int>();
75 var p = new Promise<int>();
76
76
77 var p2 = p.Error(e => 101);
77 var p2 = p.Error(e => 101);
78
78
79 p.Reject(new Exception());
79 p.Reject(new Exception());
80
80
81 Assert.AreEqual(p2.Join(), 101);
81 Assert.AreEqual(p2.Join(), 101);
82 }
82 }
83
83
84 [TestMethod]
84 [TestMethod]
85 public void ChainTest ()
85 public void ChainTest ()
86 {
86 {
87 var p1 = new Promise<int> ();
87 var p1 = new Promise<int> ();
88
88
89 var p3 = p1.Chain (x => {
89 var p3 = p1.Chain (x => {
90 var p2 = new Promise<string> ();
90 var p2 = new Promise<string> ();
91 p2.Resolve (x.ToString ());
91 p2.Resolve (x.ToString ());
92 return p2;
92 return p2;
93 });
93 });
94
94
95 p1.Resolve (100);
95 p1.Resolve (100);
96
96
97 Assert.AreEqual (p3.Join (), "100");
97 Assert.AreEqual (p3.Join (), "100");
98 }
98 }
99
99
100 [TestMethod]
100 [TestMethod]
101 public void PoolTest ()
101 public void PoolTest ()
102 {
102 {
103 var pid = Thread.CurrentThread.ManagedThreadId;
103 var pid = Thread.CurrentThread.ManagedThreadId;
104 var p = AsyncPool.Invoke (() => Thread.CurrentThread.ManagedThreadId);
104 var p = AsyncPool.Invoke (() => Thread.CurrentThread.ManagedThreadId);
105
105
106 Assert.AreNotEqual (pid, p.Join ());
106 Assert.AreNotEqual (pid, p.Join ());
107 }
107 }
108
108
109 [TestMethod]
109 [TestMethod]
110 public void WorkerPoolSizeTest() {
110 public void WorkerPoolSizeTest() {
111 var pool = new WorkerPool(5,10);
111 var pool = new WorkerPool(5,10);
112
112
113 Assert.AreEqual(5, pool.ThreadCount);
113 Assert.AreEqual(5, pool.ThreadCount);
114
114
115 pool.Invoke(() => { Thread.Sleep(1000); return 10; });
115 pool.Invoke(() => { Thread.Sleep(1000); return 10; });
116 pool.Invoke(() => { Thread.Sleep(1000); return 10; });
116 pool.Invoke(() => { Thread.Sleep(1000); return 10; });
117 pool.Invoke(() => { Thread.Sleep(1000); return 10; });
117 pool.Invoke(() => { Thread.Sleep(1000); return 10; });
118
118
119 Assert.AreEqual(5, pool.ThreadCount);
119 Assert.AreEqual(5, pool.ThreadCount);
120
120
121 for (int i = 0; i < 100; i++)
121 for (int i = 0; i < 100; i++)
122 pool.Invoke(() => { Thread.Sleep(1000); return 10; });
122 pool.Invoke(() => { Thread.Sleep(1000); return 10; });
123 Assert.AreEqual(10, pool.ThreadCount);
123 Assert.AreEqual(10, pool.ThreadCount);
124 }
124 }
125
125
126 [TestMethod]
126 [TestMethod]
127 public void WorkerPoolCorrectTest() {
127 public void WorkerPoolCorrectTest() {
128 var pool = new WorkerPool(5, 20);
128 var pool = new WorkerPool(5, 20);
129
129
130 var count = 0;
130 var count = 0;
131 for (int i = 0; i < 1000; i++)
131 for (int i = 0; i < 1000; i++)
132 pool
132 pool
133 .Invoke(() => 1)
133 .Invoke(() => 1)
134 .Then(x => Interlocked.Add(ref count, x));
134 .Then(x => Interlocked.Add(ref count, x));
135
135
136 Assert.AreEqual(1000, count);
136 Assert.AreEqual(1000, count);
137 }
137 }
138
138
139 [TestMethod]
139 [TestMethod]
140 public void MTQueueTest() {
141 var queue = new MTQueue<int>();
142 var pool = new WorkerPool(5, 20);
143
144 int res;
145
146 queue.Enqueue(10);
147 Assert.IsTrue(queue.TryDequeue(out res));
148 Assert.AreEqual(10, res);
149 Assert.IsFalse(queue.TryDequeue(out res));
150
151 for (int i = 0; i < 1000; i++)
152 queue.Enqueue(i);
153
154 for (int i = 0; i < 1000; i++) {
155 queue.TryDequeue(out res);
156 Assert.AreEqual(i, res);
157 }
158
159 int writers = 0;
160 int readers = 0;
161 var stop = new ManualResetEvent(false);
162 int total = 0;
163
164 int itemsPerWriter = 1000;
165 int writersCount = 3;
166
167 for (int i = 0; i < writersCount; i++) {
168 Interlocked.Increment(ref writers);
169 var wn = i;
170 AsyncPool
171 .InvokeNewThread(() => {
172 Console.WriteLine("Started writer: {0}", wn);
173 for (int ii = 0; ii < itemsPerWriter; ii++) {
174 queue.Enqueue(1);
175 Thread.Sleep(1);
176 }
177 Console.WriteLine("Stopped writer: {0}", wn);
178 return 1;
179 })
180 .Then(x => Interlocked.Decrement(ref writers) );
181 }
182
183 for (int i = 0; i < 10; i++) {
184 Interlocked.Increment(ref readers);
185 var wn = i;
186 AsyncPool
187 .InvokeNewThread(() => {
188 int t;
189 Console.WriteLine("Started reader: {0}", wn);
190 do {
191 while (queue.TryDequeue(out t))
192 Interlocked.Add(ref total, t);
193 Thread.Sleep(0);
194 } while (writers > 0);
195 Console.WriteLine("Stopped reader: {0}", wn);
196 return 1;
197 })
198 .Then(x => {
199 Interlocked.Decrement(ref readers);
200 if (readers == 0)
201 stop.Set();
202 });
203 }
204
205 stop.WaitOne();
206
207 Assert.AreEqual(itemsPerWriter * writersCount, total);
208 }
209
210 [TestMethod]
140 public void ComplexCase1Test() {
211 public void ComplexCase1Test() {
141 var flags = new bool[3];
212 var flags = new bool[3];
142
213
143 // op1 (aync 200ms) => op2 (async 200ms) => op3 (sync map)
214 // op1 (aync 200ms) => op2 (async 200ms) => op3 (sync map)
144
215
145 var p = PromiseHelper
216 var p = PromiseHelper
146 .Sleep(200, "Alan")
217 .Sleep(200, "Alan")
147 .Cancelled(() => flags[0] = true)
218 .Cancelled(() => flags[0] = true)
148 .Chain(x =>
219 .Chain(x =>
149 PromiseHelper
220 PromiseHelper
150 .Sleep(200, "Hi, " + x)
221 .Sleep(200, "Hi, " + x)
151 .Map( y => y )
222 .Map( y => y )
152 .Cancelled(() => flags[1] = true)
223 .Cancelled(() => flags[1] = true)
153 )
224 )
154 .Cancelled(() => flags[2] = true);
225 .Cancelled(() => flags[2] = true);
155 Thread.Sleep(300);
226 Thread.Sleep(300);
156 p.Cancel();
227 p.Cancel();
157 try {
228 try {
158 Assert.AreEqual(p.Join(), "Hi, Alan");
229 Assert.AreEqual(p.Join(), "Hi, Alan");
159 Assert.Fail("Shouldn't get here");
230 Assert.Fail("Shouldn't get here");
160 } catch(OperationCanceledException) {
231 } catch(OperationCanceledException) {
161 }
232 }
162
233
163 Assert.IsFalse(flags[0]);
234 Assert.IsFalse(flags[0]);
164 Assert.IsTrue(flags[1]);
235 Assert.IsTrue(flags[1]);
165 Assert.IsTrue(flags[2]);
236 Assert.IsTrue(flags[2]);
166 }
237 }
167 }
238 }
168 }
239 }
169
240
1 NO CONTENT: modified file, binary diff hidden
NO CONTENT: modified file, binary diff hidden
@@ -1,53 +1,54
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 <ProductVersion>10.0.0</ProductVersion>
6 <ProductVersion>10.0.0</ProductVersion>
7 <SchemaVersion>2.0</SchemaVersion>
7 <SchemaVersion>2.0</SchemaVersion>
8 <ProjectGuid>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</ProjectGuid>
8 <ProjectGuid>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</ProjectGuid>
9 <OutputType>Library</OutputType>
9 <OutputType>Library</OutputType>
10 <RootNamespace>Implab</RootNamespace>
10 <RootNamespace>Implab</RootNamespace>
11 <AssemblyName>Implab</AssemblyName>
11 <AssemblyName>Implab</AssemblyName>
12 </PropertyGroup>
12 </PropertyGroup>
13 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
13 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
14 <DebugSymbols>true</DebugSymbols>
14 <DebugSymbols>true</DebugSymbols>
15 <DebugType>full</DebugType>
15 <DebugType>full</DebugType>
16 <Optimize>false</Optimize>
16 <Optimize>false</Optimize>
17 <OutputPath>bin\Debug</OutputPath>
17 <OutputPath>bin\Debug</OutputPath>
18 <DefineConstants>DEBUG;</DefineConstants>
18 <DefineConstants>DEBUG;</DefineConstants>
19 <ErrorReport>prompt</ErrorReport>
19 <ErrorReport>prompt</ErrorReport>
20 <WarningLevel>4</WarningLevel>
20 <WarningLevel>4</WarningLevel>
21 <ConsolePause>false</ConsolePause>
21 <ConsolePause>false</ConsolePause>
22 </PropertyGroup>
22 </PropertyGroup>
23 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
23 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
24 <DebugType>full</DebugType>
24 <DebugType>full</DebugType>
25 <Optimize>true</Optimize>
25 <Optimize>true</Optimize>
26 <OutputPath>bin\Release</OutputPath>
26 <OutputPath>bin\Release</OutputPath>
27 <ErrorReport>prompt</ErrorReport>
27 <ErrorReport>prompt</ErrorReport>
28 <WarningLevel>4</WarningLevel>
28 <WarningLevel>4</WarningLevel>
29 <ConsolePause>false</ConsolePause>
29 <ConsolePause>false</ConsolePause>
30 </PropertyGroup>
30 </PropertyGroup>
31 <ItemGroup>
31 <ItemGroup>
32 <Reference Include="System" />
32 <Reference Include="System" />
33 </ItemGroup>
33 </ItemGroup>
34 <ItemGroup>
34 <ItemGroup>
35 <Compile Include="ICancellable.cs" />
35 <Compile Include="ICancellable.cs" />
36 <Compile Include="IProgressHandler.cs" />
36 <Compile Include="IProgressHandler.cs" />
37 <Compile Include="IProgressNotifier.cs" />
37 <Compile Include="IProgressNotifier.cs" />
38 <Compile Include="IPromise.cs" />
38 <Compile Include="IPromise.cs" />
39 <Compile Include="ITaskController.cs" />
39 <Compile Include="ITaskController.cs" />
40 <Compile Include="ManagedPromise.cs" />
40 <Compile Include="ManagedPromise.cs" />
41 <Compile Include="Parallels\MTQueue.cs" />
41 <Compile Include="Parallels\WorkerPool.cs" />
42 <Compile Include="Parallels\WorkerPool.cs" />
42 <Compile Include="PromiseState.cs" />
43 <Compile Include="PromiseState.cs" />
43 <Compile Include="TaskController.cs" />
44 <Compile Include="TaskController.cs" />
44 <Compile Include="ProgressInitEventArgs.cs" />
45 <Compile Include="ProgressInitEventArgs.cs" />
45 <Compile Include="Properties\AssemblyInfo.cs" />
46 <Compile Include="Properties\AssemblyInfo.cs" />
46 <Compile Include="Promise.cs" />
47 <Compile Include="Promise.cs" />
47 <Compile Include="Parallels\AsyncPool.cs" />
48 <Compile Include="Parallels\AsyncPool.cs" />
48 <Compile Include="Safe.cs" />
49 <Compile Include="Safe.cs" />
49 <Compile Include="ValueEventArgs.cs" />
50 <Compile Include="ValueEventArgs.cs" />
50 </ItemGroup>
51 </ItemGroup>
51 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
52 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
52 <ItemGroup />
53 <ItemGroup />
53 </Project> No newline at end of file
54 </Project>
@@ -1,28 +1,45
1 using System;
1 using System;
2 using System.Threading;
2 using System.Threading;
3
3
4 namespace Implab.Parallels {
4 namespace Implab.Parallels {
5 /// <summary>
5 /// <summary>
6 /// Класс для распаралСливания Π·Π°Π΄Π°Ρ‡.
6 /// Класс для распаралСливания Π·Π°Π΄Π°Ρ‡.
7 /// </summary>
7 /// </summary>
8 /// <remarks>
8 /// <remarks>
9 /// Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Π΄Π°Π½Π½Ρ‹ΠΉ класс ΠΈ лямда выраТСния ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π°ΡΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΠΈΡ‚ΡŒ
9 /// Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Π΄Π°Π½Π½Ρ‹ΠΉ класс ΠΈ лямда выраТСния ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π°ΡΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΠΈΡ‚ΡŒ
10 /// вычислСния, для этого ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ концСпция ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
10 /// вычислСния, для этого ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ концСпция ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
11 /// </remarks>
11 /// </remarks>
12 public static class AsyncPool {
12 public static class AsyncPool {
13
13
14 public static Promise<T> Invoke<T>(Func<T> func) {
14 public static Promise<T> Invoke<T>(Func<T> func) {
15 var p = new Promise<T>();
15 var p = new Promise<T>();
16
16
17 ThreadPool.QueueUserWorkItem(param => {
17 ThreadPool.QueueUserWorkItem(param => {
18 try {
18 try {
19 p.Resolve(func());
19 p.Resolve(func());
20 } catch(Exception e) {
20 } catch(Exception e) {
21 p.Reject(e);
21 p.Reject(e);
22 }
22 }
23 });
23 });
24
24
25 return p;
25 return p;
26 }
26 }
27
28 public static Promise<T> InvokeNewThread<T>(Func<T> func) {
29 var p = new Promise<T>();
30
31 var worker = new Thread(() => {
32 try {
33 p.Resolve(func());
34 } catch (Exception e) {
35 p.Reject(e);
36 }
37 });
38 worker.IsBackground = true;
39
40 worker.Start();
41
42 return p;
43 }
27 }
44 }
28 }
45 }
@@ -1,543 +1,543
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
6
7 namespace Implab {
7 namespace Implab {
8
8
9 public delegate void ErrorHandler(Exception e);
9 public delegate void ErrorHandler(Exception e);
10 public delegate T ErrorHandler<out T>(Exception e);
10 public delegate T ErrorHandler<out T>(Exception e);
11 public delegate void ResultHandler<in T>(T result);
11 public delegate void ResultHandler<in T>(T result);
12 public delegate TNew ResultMapper<in TSrc, out TNew>(TSrc result);
12 public delegate TNew ResultMapper<in TSrc, out TNew>(TSrc result);
13 public delegate Promise<TNew> ChainedOperation<in TSrc, TNew>(TSrc result);
13 public delegate Promise<TNew> ChainedOperation<in TSrc, 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 {
49 public class Promise<T> : IPromise {
50
50
51 struct ResultHandlerInfo {
51 struct ResultHandlerInfo {
52 public ResultHandler<T> resultHandler;
52 public ResultHandler<T> resultHandler;
53 public ErrorHandler errorHandler;
53 public ErrorHandler errorHandler;
54 }
54 }
55
55
56 readonly IPromise m_parent;
56 readonly IPromise m_parent;
57
57
58 LinkedList<ResultHandlerInfo> m_resultHandlers = new LinkedList<ResultHandlerInfo>();
58 LinkedList<ResultHandlerInfo> m_resultHandlers = new LinkedList<ResultHandlerInfo>();
59 LinkedList<Action> m_cancelHandlers = new LinkedList<Action>();
59 LinkedList<Action> m_cancelHandlers = new LinkedList<Action>();
60
60
61 readonly object m_lock = new Object();
61 readonly object m_lock = new Object();
62 readonly bool m_cancellable;
62 readonly bool m_cancellable;
63 int m_childrenCount = 0;
63 int m_childrenCount = 0;
64
64
65 PromiseState m_state;
65 PromiseState m_state;
66 T m_result;
66 T m_result;
67 Exception m_error;
67 Exception m_error;
68
68
69 public Promise() {
69 public Promise() {
70 m_cancellable = true;
70 m_cancellable = true;
71 }
71 }
72
72
73 public Promise(IPromise parent, bool cancellable) {
73 public Promise(IPromise parent, bool cancellable) {
74 m_cancellable = cancellable;
74 m_cancellable = cancellable;
75 m_parent = parent;
75 m_parent = parent;
76 if (parent != null)
76 if (parent != null)
77 parent.HandleCancelled(InternalCancel);
77 parent.HandleCancelled(InternalCancel);
78 }
78 }
79
79
80 void InternalCancel() {
80 void InternalCancel() {
81 // don't try to cancel parent :)
81 // don't try to cancel parent :)
82 Cancel(false);
82 Cancel(false);
83 }
83 }
84
84
85 /// <summary>
85 /// <summary>
86 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ.
86 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ.
87 /// </summary>
87 /// </summary>
88 /// <param name="result">Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния.</param>
88 /// <param name="result">Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния.</param>
89 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
89 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
90 public void Resolve(T result) {
90 public void Resolve(T result) {
91 lock (this) {
91 lock (m_lock) {
92 if (m_state == PromiseState.Cancelled)
92 if (m_state == PromiseState.Cancelled)
93 return;
93 return;
94 if (m_state != PromiseState.Unresolved)
94 if (m_state != PromiseState.Unresolved)
95 throw new InvalidOperationException("The promise is already resolved");
95 throw new InvalidOperationException("The promise is already resolved");
96 m_result = result;
96 m_result = result;
97 m_state = PromiseState.Resolved;
97 m_state = PromiseState.Resolved;
98 }
98 }
99
99
100 OnStateChanged();
100 OnStateChanged();
101 }
101 }
102
102
103 /// <summary>
103 /// <summary>
104 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ошибкС
104 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ошибкС
105 /// </summary>
105 /// </summary>
106 /// <param name="error">Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ</param>
106 /// <param name="error">Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ</param>
107 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
107 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
108 public void Reject(Exception error) {
108 public void Reject(Exception error) {
109 lock (this) {
109 lock (m_lock) {
110 if (m_state == PromiseState.Cancelled)
110 if (m_state == PromiseState.Cancelled)
111 return;
111 return;
112 if (m_state != PromiseState.Unresolved)
112 if (m_state != PromiseState.Unresolved)
113 throw new InvalidOperationException("The promise is already resolved");
113 throw new InvalidOperationException("The promise is already resolved");
114 m_error = error;
114 m_error = error;
115 m_state = PromiseState.Rejected;
115 m_state = PromiseState.Rejected;
116 }
116 }
117
117
118 OnStateChanged();
118 OnStateChanged();
119 }
119 }
120
120
121 /// <summary>
121 /// <summary>
122 /// ΠžΡ‚ΠΌΠ΅Π½ΡΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.
122 /// ΠžΡ‚ΠΌΠ΅Π½ΡΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.
123 /// </summary>
123 /// </summary>
124 /// <returns><c>true</c> ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΡ Π±Ρ‹Π»Π° ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Π°, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π½Π΅ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹.<c>false</c> ΠΎΡ‚ΠΌΠ΅Π½Π° Π½Π΅ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π°, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ ΠΎΡ‚Ρ€Π°Π±ΠΎΡ‚Π°Π»ΠΈ.</returns>
124 /// <returns><c>true</c> ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΡ Π±Ρ‹Π»Π° ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Π°, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π½Π΅ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹.<c>false</c> ΠΎΡ‚ΠΌΠ΅Π½Π° Π½Π΅ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π°, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ ΠΎΡ‚Ρ€Π°Π±ΠΎΡ‚Π°Π»ΠΈ.</returns>
125 public bool Cancel() {
125 public bool Cancel() {
126 return Cancel(true);
126 return Cancel(true);
127 }
127 }
128
128
129 /// <summary>
129 /// <summary>
130 /// Adds new handlers to this promise.
130 /// Adds new handlers to this promise.
131 /// </summary>
131 /// </summary>
132 /// <param name="success">The handler of the successfully completed operation.
132 /// <param name="success">The handler of the successfully completed operation.
133 /// This handler will recieve an operation result as a parameter.</param>
133 /// This handler will recieve an operation result as a parameter.</param>
134 /// <param name="error">Handles an exception that may occur during the operation.</param>
134 /// <param name="error">Handles an exception that may occur during the operation.</param>
135 /// <returns>The new promise chained to this one.</returns>
135 /// <returns>The new promise chained to this one.</returns>
136 public Promise<T> Then(ResultHandler<T> success, ErrorHandler error) {
136 public Promise<T> Then(ResultHandler<T> success, ErrorHandler error) {
137 if (success == null && error == null)
137 if (success == null && error == null)
138 return this;
138 return this;
139
139
140 var medium = new Promise<T>(this, true);
140 var medium = new Promise<T>(this, true);
141
141
142 var handlerInfo = new ResultHandlerInfo();
142 var handlerInfo = new ResultHandlerInfo();
143
143
144 if (success != null)
144 if (success != null)
145 handlerInfo.resultHandler = x => {
145 handlerInfo.resultHandler = x => {
146 success(x);
146 success(x);
147 medium.Resolve(x);
147 medium.Resolve(x);
148 };
148 };
149 else
149 else
150 handlerInfo.resultHandler = medium.Resolve;
150 handlerInfo.resultHandler = medium.Resolve;
151
151
152 if (error != null)
152 if (error != null)
153 handlerInfo.errorHandler = x => {
153 handlerInfo.errorHandler = x => {
154 try {
154 try {
155 error(x);
155 error(x);
156 } catch { }
156 } catch { }
157 medium.Reject(x);
157 medium.Reject(x);
158 };
158 };
159 else
159 else
160 handlerInfo.errorHandler = medium.Reject;
160 handlerInfo.errorHandler = medium.Reject;
161
161
162 AddHandler(handlerInfo);
162 AddHandler(handlerInfo);
163
163
164 return medium;
164 return medium;
165 }
165 }
166
166
167 /// <summary>
167 /// <summary>
168 /// Adds new handlers to this promise.
168 /// Adds new handlers to this promise.
169 /// </summary>
169 /// </summary>
170 /// <param name="success">The handler of the successfully completed operation.
170 /// <param name="success">The handler of the successfully completed operation.
171 /// This handler will recieve an operation result as a parameter.</param>
171 /// This handler will recieve an operation result as a parameter.</param>
172 /// <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>
172 /// <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>
173 /// <returns>The new promise chained to this one.</returns>
173 /// <returns>The new promise chained to this one.</returns>
174 public Promise<T> Then(ResultHandler<T> success, ErrorHandler<T> error) {
174 public Promise<T> Then(ResultHandler<T> success, ErrorHandler<T> error) {
175 if (success == null && error == null)
175 if (success == null && error == null)
176 return this;
176 return this;
177
177
178 var medium = new Promise<T>(this, true);
178 var medium = new Promise<T>(this, true);
179
179
180 var handlerInfo = new ResultHandlerInfo();
180 var handlerInfo = new ResultHandlerInfo();
181
181
182 if (success != null)
182 if (success != null)
183 handlerInfo.resultHandler = x => {
183 handlerInfo.resultHandler = x => {
184 success(x);
184 success(x);
185 medium.Resolve(x);
185 medium.Resolve(x);
186 };
186 };
187 else
187 else
188 handlerInfo.resultHandler = medium.Resolve;
188 handlerInfo.resultHandler = medium.Resolve;
189
189
190 if (error != null)
190 if (error != null)
191 handlerInfo.errorHandler = x => {
191 handlerInfo.errorHandler = x => {
192 try {
192 try {
193 medium.Resolve(error(x));
193 medium.Resolve(error(x));
194 } catch { }
194 } catch { }
195 medium.Reject(x);
195 medium.Reject(x);
196 };
196 };
197 else
197 else
198 handlerInfo.errorHandler = medium.Reject;
198 handlerInfo.errorHandler = medium.Reject;
199
199
200 AddHandler(handlerInfo);
200 AddHandler(handlerInfo);
201
201
202 return medium;
202 return medium;
203 }
203 }
204
204
205
205
206 public Promise<T> Then(ResultHandler<T> success) {
206 public Promise<T> Then(ResultHandler<T> success) {
207 if (success == null)
207 if (success == null)
208 return this;
208 return this;
209
209
210 var medium = new Promise<T>(this, true);
210 var medium = new Promise<T>(this, true);
211
211
212 var handlerInfo = new ResultHandlerInfo();
212 var handlerInfo = new ResultHandlerInfo();
213
213
214 if (success != null)
214 if (success != null)
215 handlerInfo.resultHandler = x => {
215 handlerInfo.resultHandler = x => {
216 success(x);
216 success(x);
217 medium.Resolve(x);
217 medium.Resolve(x);
218 };
218 };
219 else
219 else
220 handlerInfo.resultHandler = medium.Resolve;
220 handlerInfo.resultHandler = medium.Resolve;
221
221
222 handlerInfo.errorHandler = medium.Reject;
222 handlerInfo.errorHandler = medium.Reject;
223
223
224 AddHandler(handlerInfo);
224 AddHandler(handlerInfo);
225
225
226 return medium;
226 return medium;
227 }
227 }
228
228
229 public Promise<T> Error(ErrorHandler error) {
229 public Promise<T> Error(ErrorHandler error) {
230 return Then(null, error);
230 return Then(null, error);
231 }
231 }
232
232
233 /// <summary>
233 /// <summary>
234 /// Handles error and allows to keep the promise.
234 /// Handles error and allows to keep the promise.
235 /// </summary>
235 /// </summary>
236 /// <remarks>
236 /// <remarks>
237 /// If the specified handler throws an exception, this exception will be used to reject the promise.
237 /// If the specified handler throws an exception, this exception will be used to reject the promise.
238 /// </remarks>
238 /// </remarks>
239 /// <param name="handler">The error handler which returns the result of the promise.</param>
239 /// <param name="handler">The error handler which returns the result of the promise.</param>
240 /// <returns>New promise.</returns>
240 /// <returns>New promise.</returns>
241 public Promise<T> Error(ErrorHandler<T> handler) {
241 public Promise<T> Error(ErrorHandler<T> handler) {
242 if (handler == null)
242 if (handler == null)
243 return this;
243 return this;
244
244
245 var medium = new Promise<T>(this, true);
245 var medium = new Promise<T>(this, true);
246
246
247 AddHandler(new ResultHandlerInfo {
247 AddHandler(new ResultHandlerInfo {
248 errorHandler = e => {
248 errorHandler = e => {
249 try {
249 try {
250 medium.Resolve(handler(e));
250 medium.Resolve(handler(e));
251 } catch (Exception e2) {
251 } catch (Exception e2) {
252 medium.Reject(e2);
252 medium.Reject(e2);
253 }
253 }
254 }
254 }
255 });
255 });
256
256
257 return medium;
257 return medium;
258 }
258 }
259
259
260 public Promise<T> Anyway(Action handler) {
260 public Promise<T> Anyway(Action handler) {
261 if (handler == null)
261 if (handler == null)
262 return this;
262 return this;
263
263
264 var medium = new Promise<T>();
264 var medium = new Promise<T>();
265
265
266 AddHandler(new ResultHandlerInfo {
266 AddHandler(new ResultHandlerInfo {
267 resultHandler = x => {
267 resultHandler = x => {
268 // to avoid handler being called multiple times we handle exception by ourselfs
268 // to avoid handler being called multiple times we handle exception by ourselfs
269 try {
269 try {
270 handler();
270 handler();
271 medium.Resolve(x);
271 medium.Resolve(x);
272 } catch (Exception e) {
272 } catch (Exception e) {
273 medium.Reject(e);
273 medium.Reject(e);
274 }
274 }
275 },
275 },
276 errorHandler = x => {
276 errorHandler = x => {
277 try {
277 try {
278 handler();
278 handler();
279 } catch { }
279 } catch { }
280 medium.Reject(x);
280 medium.Reject(x);
281 }
281 }
282 });
282 });
283
283
284 return medium;
284 return medium;
285 }
285 }
286
286
287 /// <summary>
287 /// <summary>
288 /// ΠŸΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ‚ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.
288 /// ΠŸΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ‚ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.
289 /// </summary>
289 /// </summary>
290 /// <typeparam name="TNew">Новый Ρ‚ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°.</typeparam>
290 /// <typeparam name="TNew">Новый Ρ‚ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°.</typeparam>
291 /// <param name="mapper">ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.</param>
291 /// <param name="mapper">ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.</param>
292 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
292 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
293 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
293 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
294 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ исходного обСщания.</returns>
294 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ исходного обСщания.</returns>
295 public Promise<TNew> Map<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler error) {
295 public Promise<TNew> Map<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler error) {
296 if (mapper == null)
296 if (mapper == null)
297 throw new ArgumentNullException("mapper");
297 throw new ArgumentNullException("mapper");
298
298
299 // создаСм ΠΏΡ€ΠΈΡ†Π΅ΠΏΠ»Π΅Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
299 // создаСм ΠΏΡ€ΠΈΡ†Π΅ΠΏΠ»Π΅Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
300 var chained = new Promise<TNew>();
300 var chained = new Promise<TNew>();
301
301
302 AddHandler(new ResultHandlerInfo() {
302 AddHandler(new ResultHandlerInfo() {
303 resultHandler = result => chained.Resolve(mapper(result)),
303 resultHandler = result => chained.Resolve(mapper(result)),
304 errorHandler = delegate(Exception e) {
304 errorHandler = delegate(Exception e) {
305 if (error != null)
305 if (error != null)
306 try {
306 try {
307 error(e);
307 error(e);
308 } catch { }
308 } catch { }
309 // Π² случаС ошибки Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅
309 // Π² случаС ошибки Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅
310 chained.Reject(e);
310 chained.Reject(e);
311 }
311 }
312 });
312 });
313
313
314 return chained;
314 return chained;
315 }
315 }
316
316
317 public Promise<TNew> Map<TNew>(ResultMapper<T, TNew> mapper) {
317 public Promise<TNew> Map<TNew>(ResultMapper<T, TNew> mapper) {
318 return Map(mapper, null);
318 return Map(mapper, null);
319 }
319 }
320
320
321 /// <summary>
321 /// <summary>
322 /// БцСпляСт нСсколько аснхронных ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ. Указанная асинхронная опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½Π° послС
322 /// БцСпляСт нСсколько аснхронных ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ. Указанная асинхронная опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½Π° послС
323 /// выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ, Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ использован для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ
323 /// выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ, Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ использован для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ
324 /// Π½ΠΎΠ²ΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.
324 /// Π½ΠΎΠ²ΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.
325 /// </summary>
325 /// </summary>
326 /// <typeparam name="TNew">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</typeparam>
326 /// <typeparam name="TNew">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</typeparam>
327 /// <param name="chained">Асинхронная опСрация, которая Π΄ΠΎΠ»ΠΆΠ½Π° Π±ΡƒΠ΄Π΅Ρ‚ Π½Π°Ρ‡Π°Ρ‚ΡŒΡΡ послС выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ.</param>
327 /// <param name="chained">Асинхронная опСрация, которая Π΄ΠΎΠ»ΠΆΠ½Π° Π±ΡƒΠ΄Π΅Ρ‚ Π½Π°Ρ‡Π°Ρ‚ΡŒΡΡ послС выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ.</param>
328 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
328 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
329 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Ρ‚Π΅ΠΊΡƒΠ΅Ρ‰ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
329 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Ρ‚Π΅ΠΊΡƒΠ΅Ρ‰ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
330 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ аснхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</returns>
330 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ аснхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</returns>
331 public Promise<TNew> Chain<TNew>(ChainedOperation<T, TNew> chained, ErrorHandler error) {
331 public Promise<TNew> Chain<TNew>(ChainedOperation<T, TNew> chained, ErrorHandler error) {
332
332
333 // ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ‚ связывания Π΅Ρ‰Π΅ Π½Π΅ Π½Π°Ρ‡Π°Ρ‚Π° асинхронная опСрация, поэтому Π½ΡƒΠΆΠ½ΠΎ
333 // ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ‚ связывания Π΅Ρ‰Π΅ Π½Π΅ Π½Π°Ρ‡Π°Ρ‚Π° асинхронная опСрация, поэтому Π½ΡƒΠΆΠ½ΠΎ
334 // ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ посрСдника, ΠΊ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠΎΠ΄Π²Ρ‹Π·ΡΠ²Π°Ρ‚ΡŒΡΡ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ.
334 // ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ посрСдника, ΠΊ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠΎΠ΄Π²Ρ‹Π·ΡΠ²Π°Ρ‚ΡŒΡΡ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ.
335 // ΠΊΠΎΠ³Π΄Π° Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° Ρ€Π΅Π°Π»ΡŒΠ½Π°Ρ асинхронная опСрация, ΠΎΠ½Π° ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ ΠΊ посрСднику, Ρ‡Ρ‚ΠΎΠ±Ρ‹
335 // ΠΊΠΎΠ³Π΄Π° Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° Ρ€Π΅Π°Π»ΡŒΠ½Π°Ρ асинхронная опСрация, ΠΎΠ½Π° ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ ΠΊ посрСднику, Ρ‡Ρ‚ΠΎΠ±Ρ‹
336 // ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· Π½Π΅Π³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Ρ€Π°Π±ΠΎΡ‚Ρ‹.
336 // ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· Π½Π΅Π³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Ρ€Π°Π±ΠΎΡ‚Ρ‹.
337 var medium = new Promise<TNew>(this, true);
337 var medium = new Promise<TNew>(this, true);
338
338
339 AddHandler(new ResultHandlerInfo {
339 AddHandler(new ResultHandlerInfo {
340 resultHandler = delegate(T result) {
340 resultHandler = delegate(T result) {
341 if (medium.State == PromiseState.Cancelled)
341 if (medium.State == PromiseState.Cancelled)
342 return;
342 return;
343
343
344 var promise = chained(result);
344 var promise = chained(result);
345
345
346 // notify chained operation that it's not needed
346 // notify chained operation that it's not needed
347 medium.Cancelled(() => promise.Cancel());
347 medium.Cancelled(() => promise.Cancel());
348 promise.Then(
348 promise.Then(
349 x => medium.Resolve(x),
349 x => medium.Resolve(x),
350 e => medium.Reject(e)
350 e => medium.Reject(e)
351 );
351 );
352 },
352 },
353 errorHandler = delegate(Exception e) {
353 errorHandler = delegate(Exception e) {
354 if (error != null)
354 if (error != null)
355 error(e);
355 error(e);
356 // Π² случаС ошибки Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅
356 // Π² случаС ошибки Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅
357 medium.Reject(e);
357 medium.Reject(e);
358 }
358 }
359 });
359 });
360
360
361 return medium;
361 return medium;
362 }
362 }
363
363
364 public Promise<TNew> Chain<TNew>(ChainedOperation<T, TNew> chained) {
364 public Promise<TNew> Chain<TNew>(ChainedOperation<T, TNew> chained) {
365 return Chain(chained, null);
365 return Chain(chained, null);
366 }
366 }
367
367
368 public Promise<T> Cancelled(Action handler) {
368 public Promise<T> Cancelled(Action handler) {
369 if (handler == null)
369 if (handler == null)
370 return this;
370 return this;
371 lock (m_lock) {
371 lock (m_lock) {
372 if (m_state == PromiseState.Unresolved)
372 if (m_state == PromiseState.Unresolved)
373 m_cancelHandlers.AddLast(handler);
373 m_cancelHandlers.AddLast(handler);
374 else if (m_state == PromiseState.Cancelled)
374 else if (m_state == PromiseState.Cancelled)
375 handler();
375 handler();
376 }
376 }
377 return this;
377 return this;
378 }
378 }
379
379
380 public void HandleCancelled(Action handler) {
380 public void HandleCancelled(Action handler) {
381 Cancelled(handler);
381 Cancelled(handler);
382 }
382 }
383
383
384 /// <summary>
384 /// <summary>
385 /// ДоТидаСтся ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ³ΠΎ обСщания ΠΈ Π² случаС успСха, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚
385 /// ДоТидаСтся ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ³ΠΎ обСщания ΠΈ Π² случаС успСха, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚
386 /// Π΅Π³ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС бросаСт ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.
386 /// Π΅Π³ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС бросаСт ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.
387 /// </summary>
387 /// </summary>
388 /// <remarks>
388 /// <remarks>
389 /// <para>
389 /// <para>
390 /// Если ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ обСщания Π±Ρ‹Π»ΠΎ ΠΏΡ€Π΅Ρ€Π²Π°Π½ΠΎ ΠΏΠΎ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚Ρƒ, это Π½Π΅ Π·Π½Π°Ρ‡ΠΈΡ‚,
390 /// Если ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ обСщания Π±Ρ‹Π»ΠΎ ΠΏΡ€Π΅Ρ€Π²Π°Π½ΠΎ ΠΏΠΎ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚Ρƒ, это Π½Π΅ Π·Π½Π°Ρ‡ΠΈΡ‚,
391 /// Ρ‡Ρ‚ΠΎ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±Ρ‹Π»ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½ΠΎ ΠΈΠ»ΠΈ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π² этом Ρ€ΠΎΠ΄Π΅, это Ρ‚ΠΎΠ»ΡŒΠΊΠΎ
391 /// Ρ‡Ρ‚ΠΎ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±Ρ‹Π»ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½ΠΎ ΠΈΠ»ΠΈ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π² этом Ρ€ΠΎΠ΄Π΅, это Ρ‚ΠΎΠ»ΡŒΠΊΠΎ
392 /// ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π΅Π³ΠΎ Π½Π΅ доТдались, ΠΎΠ΄Π½Π°ΠΊΠΎ всС зарСгистрированныС
392 /// ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π΅Π³ΠΎ Π½Π΅ доТдались, ΠΎΠ΄Π½Π°ΠΊΠΎ всС зарСгистрированныС
393 /// ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, ΠΊΠ°ΠΊ Π±Ρ‹Π»ΠΈ Ρ‚Π°ΠΊ ΠΎΡΡ‚Π°Π»ΠΈΡΡŒ ΠΈ ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹, ΠΊΠΎΠ³Π΄Π°
393 /// ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, ΠΊΠ°ΠΊ Π±Ρ‹Π»ΠΈ Ρ‚Π°ΠΊ ΠΎΡΡ‚Π°Π»ΠΈΡΡŒ ΠΈ ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹, ΠΊΠΎΠ³Π΄Π°
394 /// ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
394 /// ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
395 /// </para>
395 /// </para>
396 /// <para>
396 /// <para>
397 /// Π’Π°ΠΊΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π²ΠΏΠΎΠ»Π½Π΅ ΠΎΠΏΡ€Π°Π²Π΄Π°Π½ΠΎ ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΡ‚Π΅Ρ‡ΡŒ
397 /// Π’Π°ΠΊΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π²ΠΏΠΎΠ»Π½Π΅ ΠΎΠΏΡ€Π°Π²Π΄Π°Π½ΠΎ ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΡ‚Π΅Ρ‡ΡŒ
398 /// Π² Ρ‚ΠΎΡ‚ ΠΌΠΎΠΌΠ΅Π½Ρ‚, ΠΊΠΎΠ³Π΄Π° Π½Π°Ρ‡Π°Π»Π°ΡΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ², ΠΈ
398 /// Π² Ρ‚ΠΎΡ‚ ΠΌΠΎΠΌΠ΅Π½Ρ‚, ΠΊΠΎΠ³Π΄Π° Π½Π°Ρ‡Π°Π»Π°ΡΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ², ΠΈ
399 /// ΠΊ Ρ‚ΠΎΠΌΡƒ ΠΆΠ΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡ‚ΠΎΡΡ‚ΡŒ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ ΠΈ Π΅Π³ΠΎ
399 /// ΠΊ Ρ‚ΠΎΠΌΡƒ ΠΆΠ΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡ‚ΠΎΡΡ‚ΡŒ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ ΠΈ Π΅Π³ΠΎ
400 /// ΠΎΡ‚ΠΊΠ»ΠΎΠ½Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ Π½Π΅ΠΏΡ€ΠΎΠ³Π½ΠΎΠ·ΠΈΡ€ΡƒΠ΅ΠΌΠΎΠΌΡƒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρƒ.
400 /// ΠΎΡ‚ΠΊΠ»ΠΎΠ½Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ Π½Π΅ΠΏΡ€ΠΎΠ³Π½ΠΎΠ·ΠΈΡ€ΡƒΠ΅ΠΌΠΎΠΌΡƒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρƒ.
401 /// </para>
401 /// </para>
402 /// </remarks>
402 /// </remarks>
403 /// <param name="timeout">ВрСмя оТидания</param>
403 /// <param name="timeout">ВрСмя оТидания</param>
404 /// <returns>Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния обСщания</returns>
404 /// <returns>Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния обСщания</returns>
405 public T Join(int timeout) {
405 public T Join(int timeout) {
406 var evt = new ManualResetEvent(false);
406 var evt = new ManualResetEvent(false);
407 Anyway(() => evt.Set());
407 Anyway(() => evt.Set());
408 Cancelled(() => evt.Set());
408 Cancelled(() => evt.Set());
409
409
410 if (!evt.WaitOne(timeout, true))
410 if (!evt.WaitOne(timeout, true))
411 throw new TimeoutException();
411 throw new TimeoutException();
412
412
413 switch (State) {
413 switch (State) {
414 case PromiseState.Resolved:
414 case PromiseState.Resolved:
415 return m_result;
415 return m_result;
416 case PromiseState.Cancelled:
416 case PromiseState.Cancelled:
417 throw new OperationCanceledException();
417 throw new OperationCanceledException();
418 case PromiseState.Rejected:
418 case PromiseState.Rejected:
419 throw new TargetInvocationException(m_error);
419 throw new TargetInvocationException(m_error);
420 default:
420 default:
421 throw new ApplicationException(String.Format("Invalid promise state {0}", State));
421 throw new ApplicationException(String.Format("Invalid promise state {0}", State));
422 }
422 }
423 }
423 }
424
424
425 public T Join() {
425 public T Join() {
426 return Join(Timeout.Infinite);
426 return Join(Timeout.Infinite);
427 }
427 }
428
428
429 void AddHandler(ResultHandlerInfo handler) {
429 void AddHandler(ResultHandlerInfo handler) {
430 bool invokeRequired = false;
430 bool invokeRequired = false;
431
431
432 lock (m_lock) {
432 lock (m_lock) {
433 m_childrenCount++;
433 m_childrenCount++;
434 if (m_state == PromiseState.Unresolved) {
434 if (m_state == PromiseState.Unresolved) {
435 m_resultHandlers.AddLast(handler);
435 m_resultHandlers.AddLast(handler);
436 } else
436 } else
437 invokeRequired = true;
437 invokeRequired = true;
438 }
438 }
439
439
440 // ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ сам ΠΎΠ±ΡŠΠ΅ΠΊΡ‚
440 // ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ сам ΠΎΠ±ΡŠΠ΅ΠΊΡ‚
441 if (invokeRequired)
441 if (invokeRequired)
442 InvokeHandler(handler);
442 InvokeHandler(handler);
443 }
443 }
444
444
445 void InvokeHandler(ResultHandlerInfo handler) {
445 void InvokeHandler(ResultHandlerInfo handler) {
446 switch (m_state) {
446 switch (m_state) {
447 case PromiseState.Resolved:
447 case PromiseState.Resolved:
448 try {
448 try {
449 if (handler.resultHandler != null)
449 if (handler.resultHandler != null)
450 handler.resultHandler(m_result);
450 handler.resultHandler(m_result);
451 } catch (Exception e) {
451 } catch (Exception e) {
452 try {
452 try {
453 if (handler.errorHandler != null)
453 if (handler.errorHandler != null)
454 handler.errorHandler(e);
454 handler.errorHandler(e);
455 } catch { }
455 } catch { }
456 }
456 }
457 break;
457 break;
458 case PromiseState.Rejected:
458 case PromiseState.Rejected:
459 try {
459 try {
460 if (handler.errorHandler != null)
460 if (handler.errorHandler != null)
461 handler.errorHandler(m_error);
461 handler.errorHandler(m_error);
462 } catch { }
462 } catch { }
463 break;
463 break;
464 default:
464 default:
465 // do nothing
465 // do nothing
466 return;
466 return;
467 }
467 }
468 }
468 }
469
469
470 protected virtual void OnStateChanged() {
470 protected virtual void OnStateChanged() {
471 switch (m_state) {
471 switch (m_state) {
472 case PromiseState.Resolved:
472 case PromiseState.Resolved:
473 foreach (var resultHandlerInfo in m_resultHandlers)
473 foreach (var resultHandlerInfo in m_resultHandlers)
474 try {
474 try {
475 if (resultHandlerInfo.resultHandler != null)
475 if (resultHandlerInfo.resultHandler != null)
476 resultHandlerInfo.resultHandler(m_result);
476 resultHandlerInfo.resultHandler(m_result);
477 } catch (Exception e) {
477 } catch (Exception e) {
478 try {
478 try {
479 if (resultHandlerInfo.errorHandler != null)
479 if (resultHandlerInfo.errorHandler != null)
480 resultHandlerInfo.errorHandler(e);
480 resultHandlerInfo.errorHandler(e);
481 } catch { }
481 } catch { }
482 }
482 }
483 break;
483 break;
484 case PromiseState.Cancelled:
484 case PromiseState.Cancelled:
485 foreach (var cancelHandler in m_cancelHandlers)
485 foreach (var cancelHandler in m_cancelHandlers)
486 cancelHandler();
486 cancelHandler();
487 break;
487 break;
488 case PromiseState.Rejected:
488 case PromiseState.Rejected:
489 foreach (var resultHandlerInfo in m_resultHandlers)
489 foreach (var resultHandlerInfo in m_resultHandlers)
490 try {
490 try {
491 if (resultHandlerInfo.errorHandler != null)
491 if (resultHandlerInfo.errorHandler != null)
492 resultHandlerInfo.errorHandler(m_error);
492 resultHandlerInfo.errorHandler(m_error);
493 } catch { }
493 } catch { }
494 break;
494 break;
495 default:
495 default:
496 throw new InvalidOperationException(String.Format("Promise entered an invalid state {0}", m_state));
496 throw new InvalidOperationException(String.Format("Promise entered an invalid state {0}", m_state));
497 }
497 }
498
498
499 m_resultHandlers = null;
499 m_resultHandlers = null;
500 m_cancelHandlers = null;
500 m_cancelHandlers = null;
501 }
501 }
502
502
503
503
504
504
505 public bool IsExclusive {
505 public bool IsExclusive {
506 get {
506 get {
507 lock (m_lock) {
507 lock (m_lock) {
508 return m_childrenCount <= 1;
508 return m_childrenCount <= 1;
509 }
509 }
510 }
510 }
511 }
511 }
512
512
513 public PromiseState State {
513 public PromiseState State {
514 get {
514 get {
515 lock (m_lock) {
515 lock (m_lock) {
516 return m_state;
516 return m_state;
517 }
517 }
518 }
518 }
519 }
519 }
520
520
521 protected bool Cancel(bool dependencies) {
521 protected bool Cancel(bool dependencies) {
522 bool result;
522 bool result;
523
523
524 lock (m_lock) {
524 lock (m_lock) {
525 if (m_state == PromiseState.Unresolved) {
525 if (m_state == PromiseState.Unresolved) {
526 m_state = PromiseState.Cancelled;
526 m_state = PromiseState.Cancelled;
527 result = true;
527 result = true;
528 } else {
528 } else {
529 result = false;
529 result = false;
530 }
530 }
531 }
531 }
532
532
533 if (result)
533 if (result)
534 OnStateChanged();
534 OnStateChanged();
535
535
536 if (dependencies && m_parent != null && m_parent.IsExclusive) {
536 if (dependencies && m_parent != null && m_parent.IsExclusive) {
537 m_parent.Cancel();
537 m_parent.Cancel();
538 }
538 }
539
539
540 return result;
540 return result;
541 }
541 }
542 }
542 }
543 }
543 }
General Comments 0
You need to be logged in to leave comments. Login now