##// END OF EJS Templates
refactoring
cin -
r25:9bf5b23650c9 default
parent child
Show More
@@ -0,0 +1,19
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace Implab {
7 public interface IPromiseBase: ICancellable {
8 /// <summary>
9 /// Check whereather the promise has no more than one dependent promise.
10 /// </summary>
11 bool IsExclusive {
12 get;
13 }
14
15 bool IsResolved { get; }
16
17 bool IsCancelled { get; }
18 }
19 }
@@ -1,20 +1,16
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
3 using System.Linq;
4 using System.Text;
4 using System.Text;
5
5
6 namespace Implab
6 namespace Implab
7 {
7 {
8 public interface IPromise: ICancellable
8 public interface IPromise<T>: IPromiseBase
9 {
9 {
10 /// <summary>
10
11 /// Check whereather the promise has no more than one dependent promise.
11
12 /// </summary>
12
13 bool IsExclusive
14 {
15 get;
16 }
17
13
18
14
19 }
15 }
20 }
16 }
@@ -1,12 +1,14
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
3 using System.Linq;
4 using System.Text;
4 using System.Text;
5
5
6 namespace Implab {
6 namespace Implab {
7 public interface ITaskController: IProgressHandler {
7 public interface ITaskController: IProgressHandler, ICancellable {
8 bool Cancelled {
8 bool IsCancelled {
9 get;
9 get;
10 }
10 }
11
12 event EventHandler Cancelled;
11 }
13 }
12 }
14 }
@@ -1,56 +1,57
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="IPromiseBase.cs" />
39 <Compile Include="ITaskController.cs" />
40 <Compile Include="ITaskController.cs" />
40 <Compile Include="ManagedPromise.cs" />
41 <Compile Include="ManagedPromise.cs" />
41 <Compile Include="Parallels\DispatchPool.cs" />
42 <Compile Include="Parallels\DispatchPool.cs" />
42 <Compile Include="Parallels\ArrayTraits.cs" />
43 <Compile Include="Parallels\ArrayTraits.cs" />
43 <Compile Include="Parallels\MTQueue.cs" />
44 <Compile Include="Parallels\MTQueue.cs" />
44 <Compile Include="Parallels\WorkerPool.cs" />
45 <Compile Include="Parallels\WorkerPool.cs" />
45 <Compile Include="PromiseState.cs" />
46 <Compile Include="PromiseState.cs" />
46 <Compile Include="TaskController.cs" />
47 <Compile Include="TaskController.cs" />
47 <Compile Include="ProgressInitEventArgs.cs" />
48 <Compile Include="ProgressInitEventArgs.cs" />
48 <Compile Include="Properties\AssemblyInfo.cs" />
49 <Compile Include="Properties\AssemblyInfo.cs" />
49 <Compile Include="Promise.cs" />
50 <Compile Include="Promise.cs" />
50 <Compile Include="Parallels\AsyncPool.cs" />
51 <Compile Include="Parallels\AsyncPool.cs" />
51 <Compile Include="Safe.cs" />
52 <Compile Include="Safe.cs" />
52 <Compile Include="ValueEventArgs.cs" />
53 <Compile Include="ValueEventArgs.cs" />
53 </ItemGroup>
54 </ItemGroup>
54 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
55 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
55 <ItemGroup />
56 <ItemGroup />
56 </Project> No newline at end of file
57 </Project>
@@ -1,212 +1,172
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Diagnostics;
3 using System.Diagnostics;
4 using System.Linq;
4 using System.Linq;
5 using System.Text;
5 using System.Text;
6 using System.Threading;
6 using System.Threading;
7
7
8 namespace Implab.Parallels {
8 namespace Implab.Parallels {
9 public static class ArrayTraits {
9 public static class ArrayTraits {
10 class ArrayIterator<TSrc> : DispatchPool<int> {
10 class ArrayIterator<TSrc> : DispatchPool<int> {
11 readonly Action<TSrc> m_action;
11 readonly Action<TSrc> m_action;
12 readonly TSrc[] m_source;
12 readonly TSrc[] m_source;
13 readonly Promise<int> m_promise = new Promise<int>();
13 readonly Promise<int> m_promise = new Promise<int>();
14
14
15 int m_pending;
15 int m_pending;
16 int m_next;
16 int m_next;
17
17
18 public ArrayIterator(TSrc[] source, Action<TSrc> action, int threads)
18 public ArrayIterator(TSrc[] source, Action<TSrc> action, int threads)
19 : base(threads) {
19 : base(threads) {
20
20
21 Debug.Assert(source != null);
21 Debug.Assert(source != null);
22 Debug.Assert(action != null);
22 Debug.Assert(action != null);
23
23
24 m_next = 0;
24 m_next = 0;
25 m_source = source;
25 m_source = source;
26 m_pending = source.Length;
26 m_pending = source.Length;
27 m_action = action;
27 m_action = action;
28
28
29 m_promise.Anyway(() => Dispose());
29 m_promise.Anyway(() => Dispose());
30 m_promise.Cancelled(() => Dispose());
30 m_promise.Cancelled(() => Dispose());
31
31
32 InitPool();
32 InitPool();
33 }
33 }
34
34
35 public Promise<int> Promise {
35 public Promise<int> Promise {
36 get {
36 get {
37 return m_promise;
37 return m_promise;
38 }
38 }
39 }
39 }
40
40
41 protected override bool TryDequeue(out int unit) {
41 protected override bool TryDequeue(out int unit) {
42 unit = Interlocked.Increment(ref m_next) - 1;
42 unit = Interlocked.Increment(ref m_next) - 1;
43 return unit >= m_source.Length ? false : true;
43 return unit >= m_source.Length ? false : true;
44 }
44 }
45
45
46 protected override void InvokeUnit(int unit) {
46 protected override void InvokeUnit(int unit) {
47 try {
47 try {
48 m_action(m_source[unit]);
48 m_action(m_source[unit]);
49 var pending = Interlocked.Decrement(ref m_pending);
49 var pending = Interlocked.Decrement(ref m_pending);
50 if (pending == 0)
50 if (pending == 0)
51 m_promise.Resolve(m_source.Length);
51 m_promise.Resolve(m_source.Length);
52 } catch (Exception e) {
52 } catch (Exception e) {
53 m_promise.Reject(e);
53 m_promise.Reject(e);
54 }
54 }
55 }
55 }
56 }
56 }
57
57
58 class ArrayMapper<TSrc, TDst>: DispatchPool<int> {
58 class ArrayMapper<TSrc, TDst>: DispatchPool<int> {
59 readonly Func<TSrc, TDst> m_transform;
59 readonly Func<TSrc, TDst> m_transform;
60 readonly TSrc[] m_source;
60 readonly TSrc[] m_source;
61 readonly TDst[] m_dest;
61 readonly TDst[] m_dest;
62 readonly Promise<TDst[]> m_promise = new Promise<TDst[]>();
62 readonly Promise<TDst[]> m_promise = new Promise<TDst[]>();
63
63
64 int m_pending;
64 int m_pending;
65 int m_next;
65 int m_next;
66
66
67 public ArrayMapper(TSrc[] source, Func<TSrc, TDst> transform, int threads)
67 public ArrayMapper(TSrc[] source, Func<TSrc, TDst> transform, int threads)
68 : base(threads) {
68 : base(threads) {
69
69
70 Debug.Assert (source != null);
70 Debug.Assert (source != null);
71 Debug.Assert( transform != null);
71 Debug.Assert( transform != null);
72
72
73 m_next = 0;
73 m_next = 0;
74 m_source = source;
74 m_source = source;
75 m_dest = new TDst[source.Length];
75 m_dest = new TDst[source.Length];
76 m_pending = source.Length;
76 m_pending = source.Length;
77 m_transform = transform;
77 m_transform = transform;
78
78
79 m_promise.Anyway(() => Dispose());
79 m_promise.Anyway(() => Dispose());
80 m_promise.Cancelled(() => Dispose());
80 m_promise.Cancelled(() => Dispose());
81
81
82 InitPool();
82 InitPool();
83 }
83 }
84
84
85 public Promise<TDst[]> Promise {
85 public Promise<TDst[]> Promise {
86 get {
86 get {
87 return m_promise;
87 return m_promise;
88 }
88 }
89 }
89 }
90
90
91 protected override bool TryDequeue(out int unit) {
91 protected override bool TryDequeue(out int unit) {
92 unit = Interlocked.Increment(ref m_next) - 1;
92 unit = Interlocked.Increment(ref m_next) - 1;
93 return unit >= m_source.Length ? false : true;
93 return unit >= m_source.Length ? false : true;
94 }
94 }
95
95
96 protected override void InvokeUnit(int unit) {
96 protected override void InvokeUnit(int unit) {
97 try {
97 try {
98 m_dest[unit] = m_transform(m_source[unit]);
98 m_dest[unit] = m_transform(m_source[unit]);
99 var pending = Interlocked.Decrement(ref m_pending);
99 var pending = Interlocked.Decrement(ref m_pending);
100 if (pending == 0)
100 if (pending == 0)
101 m_promise.Resolve(m_dest);
101 m_promise.Resolve(m_dest);
102 } catch (Exception e) {
102 } catch (Exception e) {
103 m_promise.Reject(e);
103 m_promise.Reject(e);
104 }
104 }
105 }
105 }
106 }
106 }
107
107
108 public static Promise<TDst[]> ParallelMap<TSrc, TDst> (this TSrc[] source, Func<TSrc,TDst> transform, int threads) {
108 public static Promise<TDst[]> ParallelMap<TSrc, TDst> (this TSrc[] source, Func<TSrc,TDst> transform, int threads) {
109 if (source == null)
109 if (source == null)
110 throw new ArgumentNullException("source");
110 throw new ArgumentNullException("source");
111 if (transform == null)
111 if (transform == null)
112 throw new ArgumentNullException("transform");
112 throw new ArgumentNullException("transform");
113
113
114 var mapper = new ArrayMapper<TSrc, TDst>(source, transform, threads);
114 var mapper = new ArrayMapper<TSrc, TDst>(source, transform, threads);
115 return mapper.Promise;
115 return mapper.Promise;
116 }
116 }
117
117
118 public static Promise<int> ParallelForEach<TSrc>(this TSrc[] source, Action<TSrc> action, int threads) {
118 public static Promise<int> ParallelForEach<TSrc>(this TSrc[] source, Action<TSrc> action, int threads) {
119 if (source == null)
119 if (source == null)
120 throw new ArgumentNullException("source");
120 throw new ArgumentNullException("source");
121 if (action == null)
121 if (action == null)
122 throw new ArgumentNullException("action");
122 throw new ArgumentNullException("action");
123
123
124 var iter = new ArrayIterator<TSrc>(source, action, threads);
124 var iter = new ArrayIterator<TSrc>(source, action, threads);
125 return iter.Promise;
125 return iter.Promise;
126 }
126 }
127
127
128 public static Promise<TDst[]> ChainedMap<TSrc, TDst>(this TSrc[] source, ChainedOperation<TSrc, TDst> transform, int threads) {
128 public static Promise<TDst[]> ChainedMap<TSrc, TDst>(this TSrc[] source, ChainedOperation<TSrc, TDst> transform, int threads) {
129 if (source == null)
129 if (source == null)
130 throw new ArgumentNullException("source");
130 throw new ArgumentNullException("source");
131 if (transform == null)
131 if (transform == null)
132 throw new ArgumentNullException("transform");
132 throw new ArgumentNullException("transform");
133 if (threads <= 0)
133 if (threads <= 0)
134 throw new ArgumentOutOfRangeException("Threads number must be greater then zero");
134 throw new ArgumentOutOfRangeException("Threads number must be greater then zero");
135
135
136 var promise = new Promise<TDst[]>();
136 var promise = new Promise<TDst[]>();
137 var res = new TDst[source.Length];
137 var res = new TDst[source.Length];
138 var pending = source.Length;
138 var pending = source.Length;
139 var semaphore = new Semaphore(threads, threads);
139 var semaphore = new Semaphore(threads, threads);
140
140
141 AsyncPool.InvokeNewThread(() => {
141 AsyncPool.InvokeNewThread(() => {
142 for (int i = 0; i < source.Length; i++) {
142 for (int i = 0; i < source.Length; i++) {
143 if(promise.IsResolved)
143 if(promise.IsResolved)
144 break; // stop processing in case of error or cancellation
144 break; // stop processing in case of error or cancellation
145 var idx = i;
145 var idx = i;
146 semaphore.WaitOne();
146 semaphore.WaitOne();
147 try {
147 try {
148 var p1 = transform(source[i]);
148 var p1 = transform(source[i]);
149 p1.Anyway(() => semaphore.Release());
149 p1.Anyway(() => semaphore.Release());
150 p1.Cancelled(() => semaphore.Release());
150 p1.Cancelled(() => semaphore.Release());
151 p1.Then(
151 p1.Then(
152 x => {
152 x => {
153 res[idx] = x;
153 res[idx] = x;
154 var left = Interlocked.Decrement(ref pending);
154 var left = Interlocked.Decrement(ref pending);
155 if (left == 0)
155 if (left == 0)
156 promise.Resolve(res);
156 promise.Resolve(res);
157 },
157 },
158 e => promise.Reject(e)
158 e => promise.Reject(e)
159 );
159 );
160
160
161 } catch (Exception e) {
161 } catch (Exception e) {
162 promise.Reject(e);
162 promise.Reject(e);
163 }
163 }
164 }
164 }
165 return 0;
165 return 0;
166 });
166 });
167
167
168 return promise.Anyway(() => semaphore.Dispose());
168 return promise.Anyway(() => semaphore.Dispose());
169 }
169 }
170
170
171 /*
172 this method is pretty fast, but it may cause a stack overflow if an element transformation is made faster then the next operation is
173 be chained, in this case the syncronous callback invocation will occur
174
175 public static Promise<TDst[]> ChainedMap2<TSrc, TDst>(this TSrc[] source, ChainedOperation<TSrc, TDst> transform, int threads) {
176 if (source == null)
177 throw new ArgumentNullException("source");
178 if (transform == null)
179 throw new ArgumentNullException("transform");
180 if (threads <= 0)
181 throw new ArgumentOutOfRangeException("Threads number must be greater then zero");
182
183 var promise = new Promise<TDst[]>();
184 var res = new TDst[source.Length];
185 var index = -1; // we will start with increment
186 var len = source.Length;
187 var pending = len;
188
189 Action<int> callback = null;
190 callback = (current) => {
191 if (current < len) {
192 transform(source[current])
193 .Then(
194 x => {
195 res[current] = x;
196 if (Interlocked.Decrement(ref pending) == 0)
197 promise.Resolve(res);
198 else
199 callback(Interlocked.Increment(ref index));
200 },
201 e => promise.Reject(e)
202 );
203 }
204 };
205
206 for (int i = 0; i < threads; i++)
207 callback(Interlocked.Increment(ref index));
208 return promise;
209 }
210 */
211 }
171 }
212 }
172 }
@@ -1,564 +1,646
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Reflection;
3 using System.Reflection;
4 using System.Diagnostics;
4 using System.Diagnostics;
5 using System.Threading;
5 using System.Threading;
6 using Implab.Parallels;
6 using Implab.Parallels;
7
7
8 namespace Implab {
8 namespace Implab {
9
9
10 public delegate void ErrorHandler(Exception e);
10 public delegate void ErrorHandler(Exception e);
11 public delegate T ErrorHandler<out T>(Exception e);
11 public delegate T ErrorHandler<out T>(Exception e);
12 public delegate void ResultHandler<in T>(T result);
12 public delegate void ResultHandler<in T>(T result);
13 public delegate TNew ResultMapper<in TSrc, out TNew>(TSrc result);
13 public delegate TNew ResultMapper<in TSrc, out TNew>(TSrc result);
14 public delegate Promise<TNew> ChainedOperation<in TSrc, TNew>(TSrc result);
14 public delegate Promise<TNew> ChainedOperation<in TSrc, TNew>(TSrc result);
15
15
16 /// <summary>
16 /// <summary>
17 /// Класс для асинхронного получСния Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ². Π’Π°ΠΊ Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΠΎΠ΅ "ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅".
17 /// Класс для асинхронного получСния Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ². Π’Π°ΠΊ Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΠΎΠ΅ "ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅".
18 /// </summary>
18 /// </summary>
19 /// <typeparam name="T">Π’ΠΈΠΏ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌΠΎΠ³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°</typeparam>
19 /// <typeparam name="T">Π’ΠΈΠΏ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌΠΎΠ³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°</typeparam>
20 /// <remarks>
20 /// <remarks>
21 /// <para>БСрвис ΠΏΡ€ΠΈ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ ΠΊ Π΅Π³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρƒ Π΄Π°Π΅Ρ‚ ΠΎΠ±Π΅Ρ‰Π°ΠΈΠ½ΠΈΠ΅ ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ,
21 /// <para>БСрвис ΠΏΡ€ΠΈ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ ΠΊ Π΅Π³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρƒ Π΄Π°Π΅Ρ‚ ΠΎΠ±Π΅Ρ‰Π°ΠΈΠ½ΠΈΠ΅ ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ,
22 /// ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ² Ρ‚Π°ΠΊΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ряд ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹Ρ… Π²Ρ‹Π·ΠΎΠ²ΠΎ для получСния
22 /// ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ² Ρ‚Π°ΠΊΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ряд ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹Ρ… Π²Ρ‹Π·ΠΎΠ²ΠΎ для получСния
23 /// событий выполнСния обСщания, Ρ‚ΠΎΠ΅ΡΡ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΈ прСдоставлСнии Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ².</para>
23 /// событий выполнСния обСщания, Ρ‚ΠΎΠ΅ΡΡ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΈ прСдоставлСнии Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ².</para>
24 /// <para>
24 /// <para>
25 /// ΠžΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚Π°ΠΊ ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ с ошибкой. Для подписки Π½Π°
25 /// ΠžΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚Π°ΠΊ ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ с ошибкой. Для подписки Π½Π°
26 /// Π΄Π°Π½Π½Ρ‹Π΅ события ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Then</c>.
26 /// Π΄Π°Π½Π½Ρ‹Π΅ события ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Then</c>.
27 /// </para>
27 /// </para>
28 /// <para>
28 /// <para>
29 /// БСрвис, Π² свою ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ, ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ (Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ с ошибкой),
29 /// БСрвис, Π² свою ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ, ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ (Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ с ошибкой),
30 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Resolve</c> Π»ΠΈΠ±ΠΎ <c>Reject</c> для оповСщСния ΠΊΠ»ΠΈΠ΅Ρ‚Π½Π° ΠΎ
30 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Resolve</c> Π»ΠΈΠ±ΠΎ <c>Reject</c> для оповСщСния ΠΊΠ»ΠΈΠ΅Ρ‚Π½Π° ΠΎ
31 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ обСщания.
31 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ обСщания.
32 /// </para>
32 /// </para>
33 /// <para>
33 /// <para>
34 /// Если сСрвСр успСл Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΅Ρ‰Π΅ Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π½Π° Π½Π΅Π³ΠΎ подписался,
34 /// Если сСрвСр успСл Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΅Ρ‰Π΅ Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π½Π° Π½Π΅Π³ΠΎ подписался,
35 /// Ρ‚ΠΎ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ подписки ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΠ²ΡƒΡŽΡ‰ΠΈΠ΅ события Π² синхронном
35 /// Ρ‚ΠΎ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ подписки ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΠ²ΡƒΡŽΡ‰ΠΈΠ΅ события Π² синхронном
36 /// Ρ€Π΅ΠΆΠΈΠΌΠ΅ ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΠΎΠ²Π΅Ρ‰Π΅Π½ Π² любом случаС. Π˜Π½Π°Ρ‡Π΅, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ΡΡ Π²
36 /// Ρ€Π΅ΠΆΠΈΠΌΠ΅ ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΠΎΠ²Π΅Ρ‰Π΅Π½ Π² любом случаС. Π˜Π½Π°Ρ‡Π΅, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ΡΡ Π²
37 /// список Π² порядкС подписания ΠΈ Π² этом ΠΆΠ΅ порядкС ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ
37 /// список Π² порядкС подписания ΠΈ Π² этом ΠΆΠ΅ порядкС ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ
38 /// обСщания.
38 /// обСщания.
39 /// </para>
39 /// </para>
40 /// <para>
40 /// <para>
41 /// ΠžΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ обСщания ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Π»ΠΈΠ±ΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ
41 /// ΠžΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ обСщания ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Π»ΠΈΠ±ΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ
42 /// связанныС асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ‚Π°ΠΊΠΆΠ΅ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ обСщания. Для этого слСдуСт
42 /// связанныС асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ‚Π°ΠΊΠΆΠ΅ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ обСщания. Для этого слСдуСт
43 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ Ρ„ΠΎΡ€ΠΌΡƒ ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ <c>Then</c>.
43 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ Ρ„ΠΎΡ€ΠΌΡƒ ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ <c>Then</c>.
44 /// </para>
44 /// </para>
45 /// <para>
45 /// <para>
46 /// Π’Π°ΠΊΠΆΠ΅ Ρ…ΠΎΡ€ΠΎΡˆΠΈΠΌ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎΠΌ являСтся Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ <c>Resolve</c> ΠΈ <c>Reject</c> Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ
46 /// Π’Π°ΠΊΠΆΠ΅ Ρ…ΠΎΡ€ΠΎΡˆΠΈΠΌ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎΠΌ являСтся Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ <c>Resolve</c> ΠΈ <c>Reject</c> Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ
47 /// Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€ обСщания ΠΈΠ½Π°Ρ‡Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ΡŒ противорСчия.
47 /// Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€ обСщания ΠΈΠ½Π°Ρ‡Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ΡŒ противорСчия.
48 /// </para>
48 /// </para>
49 /// </remarks>
49 /// </remarks>
50 public class Promise<T> : IPromise {
50 public class Promise<T> : IPromise<T> {
51
51
52 struct HandlerDescriptor {
52 struct HandlerDescriptor {
53 public ResultHandler<T> resultHandler;
53 public ResultHandler<T> resultHandler;
54 public ErrorHandler errorHandler;
54 public ErrorHandler errorHandler;
55 public Action cancellHandler;
55 public Action cancellHandler;
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 }
63 }
64 }
64 }
65
65
66 public void Reject(Exception err) {
66 public void Reject(Exception err) {
67 if (errorHandler != null)
67 if (errorHandler != null)
68 try {
68 try {
69 errorHandler(err);
69 errorHandler(err);
70 } catch {
70 } catch {
71 }
71 }
72 }
72 }
73
73
74 public void Cancel() {
74 public void Cancel() {
75 if (cancellHandler != null)
75 if (cancellHandler != null)
76 try {
76 try {
77 cancellHandler();
77 cancellHandler();
78 } catch {
78 } catch {
79 }
79 }
80 }
80 }
81 }
81 }
82
82
83 const int UnresolvedSate = 0;
83 const int UnresolvedSate = 0;
84 const int TransitionalState = 1;
84 const int TransitionalState = 1;
85 const int ResolvedState = 2;
85 const int SucceededState = 2;
86 const int RejectedState = 3;
86 const int RejectedState = 3;
87 const int CancelledState = 4;
87 const int CancelledState = 4;
88
88
89 readonly IPromise m_parent;
89 readonly IPromiseBase m_parent;
90 readonly bool m_cancellable;
90 readonly bool m_cancellable;
91
91
92 int m_childrenCount = 0;
92 int m_childrenCount = 0;
93 int m_state;
93 int m_state;
94 T m_result;
94 T m_result;
95 Exception m_error;
95 Exception m_error;
96
96
97 readonly MTQueue<HandlerDescriptor> m_handlers = new MTQueue<HandlerDescriptor>();
97 readonly MTQueue<HandlerDescriptor> m_handlers = new MTQueue<HandlerDescriptor>();
98
98
99 public Promise() {
99 public Promise() {
100 m_cancellable = true;
100 m_cancellable = true;
101 }
101 }
102
102
103 public Promise(IPromise parent, bool cancellable) {
103 public Promise(IPromiseBase parent, bool cancellable) {
104 m_cancellable = cancellable;
104 m_cancellable = cancellable;
105 m_parent = parent;
105 m_parent = parent;
106 }
106 }
107
107
108 void InternalCancel() {
108 void InternalCancel() {
109 // don't try to cancel parent :)
109 // don't try to cancel parent :)
110 Cancel(false);
110 Cancel(false);
111 }
111 }
112
112
113 bool BeginTransit() {
113 bool BeginTransit() {
114 return UnresolvedSate == Interlocked.CompareExchange(ref m_state, TransitionalState, UnresolvedSate);
114 return UnresolvedSate == Interlocked.CompareExchange(ref m_state, TransitionalState, UnresolvedSate);
115 }
115 }
116
116
117 void CompleteTransit(int state) {
117 void CompleteTransit(int state) {
118 if (TransitionalState != Interlocked.CompareExchange(ref m_state, state, TransitionalState))
118 if (TransitionalState != Interlocked.CompareExchange(ref m_state, state, TransitionalState))
119 throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state");
119 throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state");
120 }
120 }
121
121
122 void WaitTransition() {
123 while (m_state == TransitionalState) {
124 /* noop */
125 }
126 }
127
122 public bool IsResolved {
128 public bool IsResolved {
123 get {
129 get {
124 return m_state > 1;
130 return m_state > 1;
125 }
131 }
126 }
132 }
127
133
128 public bool IsCancelled {
134 public bool IsCancelled {
129 get {
135 get {
130 return m_state == CancelledState;
136 return m_state == CancelledState;
131 }
137 }
132 }
138 }
133
139
134 /// <summary>
140 /// <summary>
135 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ.
141 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ.
136 /// </summary>
142 /// </summary>
137 /// <param name="result">Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния.</param>
143 /// <param name="result">Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния.</param>
138 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
144 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
139 public void Resolve(T result) {
145 public void Resolve(T result) {
140 if (BeginTransit()) {
146 if (BeginTransit()) {
141 m_result = result;
147 m_result = result;
142 CompleteTransit(ResolvedState);
148 CompleteTransit(SucceededState);
143 OnStateChanged();
149 OnStateChanged();
144 } else if (m_state != CancelledState)
150 } else {
151 WaitTransition();
152 if (m_state != CancelledState)
145 throw new InvalidOperationException("The promise is already resolved");
153 throw new InvalidOperationException("The promise is already resolved");
146 }
154 }
155 }
147
156
148 /// <summary>
157 /// <summary>
149 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ошибкС
158 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ошибкС
150 /// </summary>
159 /// </summary>
151 /// <remarks>
160 /// <remarks>
152 /// ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС, ΠΏΡ€ΠΈ Π΅Π³ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ сразу нСсколько ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²
161 /// ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС, ΠΏΡ€ΠΈ Π΅Π³ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ сразу нСсколько ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²
153 /// ΠΌΠΎΠ³Ρƒ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ, ΠΏΡ€ΠΈ этом Ρ‚ΠΎΠ»ΡŒΠΊΠΎ пСрвая Π±ΡƒΠ΄Π΅Ρ‚ использована Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅
162 /// ΠΌΠΎΠ³Ρƒ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ, ΠΏΡ€ΠΈ этом Ρ‚ΠΎΠ»ΡŒΠΊΠΎ пСрвая Π±ΡƒΠ΄Π΅Ρ‚ использована Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅
154 /// Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΡ€ΠΎΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹.
163 /// Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΡ€ΠΎΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹.
155 /// </remarks>
164 /// </remarks>
156 /// <param name="error">Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ</param>
165 /// <param name="error">Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ</param>
157 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
166 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
158 public void Reject(Exception error) {
167 public void Reject(Exception error) {
159 if (BeginTransit()) {
168 if (BeginTransit()) {
160 m_error = error;
169 m_error = error;
161 CompleteTransit(RejectedState);
170 CompleteTransit(RejectedState);
162 OnStateChanged();
171 OnStateChanged();
163 } else if (m_state == ResolvedState)
172 } else {
173 WaitTransition();
174 if (m_state == SucceededState)
164 throw new InvalidOperationException("The promise is already resolved");
175 throw new InvalidOperationException("The promise is already resolved");
165 }
176 }
177 }
166
178
167 /// <summary>
179 /// <summary>
168 /// ΠžΡ‚ΠΌΠ΅Π½ΡΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.
180 /// ΠžΡ‚ΠΌΠ΅Π½ΡΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.
169 /// </summary>
181 /// </summary>
170 /// <returns><c>true</c> ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΡ Π±Ρ‹Π»Π° ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Π°, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π½Π΅ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹.<c>false</c> ΠΎΡ‚ΠΌΠ΅Π½Π° Π½Π΅ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π°, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ ΠΎΡ‚Ρ€Π°Π±ΠΎΡ‚Π°Π»ΠΈ.</returns>
182 /// <returns><c>true</c> ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΡ Π±Ρ‹Π»Π° ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Π°, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π½Π΅ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹.<c>false</c> ΠΎΡ‚ΠΌΠ΅Π½Π° Π½Π΅ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π°, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ ΠΎΡ‚Ρ€Π°Π±ΠΎΡ‚Π°Π»ΠΈ.</returns>
171 public bool Cancel() {
183 public bool Cancel() {
172 return Cancel(true);
184 return Cancel(true);
173 }
185 }
174
186
175 /// <summary>
187 /// <summary>
176 /// Adds new handlers to this promise.
188 /// Adds new handlers to this promise.
177 /// </summary>
189 /// </summary>
178 /// <param name="success">The handler of the successfully completed operation.
190 /// <param name="success">The handler of the successfully completed operation.
179 /// This handler will recieve an operation result as a parameter.</param>
191 /// This handler will recieve an operation result as a parameter.</param>
180 /// <param name="error">Handles an exception that may occur during the operation.</param>
192 /// <param name="error">Handles an exception that may occur during the operation.</param>
181 /// <returns>The new promise chained to this one.</returns>
193 /// <returns>The new promise chained to this one.</returns>
182 public Promise<T> Then(ResultHandler<T> success, ErrorHandler error) {
194 public Promise<T> Then(ResultHandler<T> success, ErrorHandler error) {
183 if (success == null && error == null)
195 if (success == null && error == null)
184 return this;
196 return this;
185
197
186 var medium = new Promise<T>(this, true);
198 var medium = new Promise<T>(this, true);
187
199
188 ResultHandler<T> resultHandler;
200 ResultHandler<T> resultHandler;
189 if (success != null)
201 if (success != null)
190 resultHandler = x => {
202 resultHandler = x => {
191 success(x);
203 success(x);
192 medium.Resolve(x);
204 medium.Resolve(x);
193 };
205 };
194 else
206 else
195 resultHandler = medium.Resolve;
207 resultHandler = medium.Resolve;
196
208
197 ErrorHandler errorHandler;
209 ErrorHandler errorHandler;
198 if (error != null)
210 if (error != null)
199 errorHandler = x => {
211 errorHandler = x => {
212 // нСсмотря Π½Π° Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки вызываСтся бСзопасно,
213 // Ρ‚.Π΅. возникшиС Π² Π½Π΅ΠΌ ошибки Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠΎΠ΄Π°Π²Π»Π΅Π½Ρ‹, Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ
214 // Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ ошибка Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π° дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ
200 try {
215 try {
201 error(x);
216 error(x);
202 } catch { }
217 } catch { }
203 medium.Reject(x);
218 medium.Reject(x);
204 };
219 };
205 else
220 else
206 errorHandler = medium.Reject;
221 errorHandler = medium.Reject;
207
222
208 AddHandler(resultHandler, errorHandler, medium.InternalCancel);
223 AddHandler(resultHandler, errorHandler, medium.InternalCancel);
209
224
210 return medium;
225 return medium;
211 }
226 }
212
227
213 /// <summary>
228 /// <summary>
214 /// Adds new handlers to this promise.
229 /// Adds new handlers to this promise.
215 /// </summary>
230 /// </summary>
216 /// <param name="success">The handler of the successfully completed operation.
231 /// <param name="success">The handler of the successfully completed operation.
217 /// This handler will recieve an operation result as a parameter.</param>
232 /// This handler will recieve an operation result as a parameter.</param>
218 /// <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>
233 /// <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>
219 /// <returns>The new promise chained to this one.</returns>
234 /// <returns>The new promise chained to this one.</returns>
220 public Promise<T> Then(ResultHandler<T> success, ErrorHandler<T> error) {
235 public Promise<T> Then(ResultHandler<T> success, ErrorHandler<T> error) {
221 if (success == null && error == null)
236 if (success == null && error == null)
222 return this;
237 return this;
223
238
224 var medium = new Promise<T>(this, true);
239 var medium = new Promise<T>(this, true);
225
240
226 ResultHandler<T> resultHandler;
241 ResultHandler<T> resultHandler;
227 ErrorHandler errorHandler;
242 ErrorHandler errorHandler;
228
243
229 if (success != null)
244 if (success != null)
230 resultHandler = x => {
245 resultHandler = x => {
231 success(x);
246 success(x);
232 medium.Resolve(x);
247 medium.Resolve(x);
233 };
248 };
234 else
249 else
235 resultHandler = medium.Resolve;
250 resultHandler = medium.Resolve;
236
251
237 if (error != null)
252 if (error != null)
238 errorHandler = x => {
253 errorHandler = x => {
239 try {
254 try {
240 medium.Resolve(error(x));
255 medium.Resolve(error(x));
241 } catch { }
256 } catch(Exception e) {
242 medium.Reject(x);
257 medium.Reject(e);
258 }
243 };
259 };
244 else
260 else
245 errorHandler = medium.Reject;
261 errorHandler = medium.Reject;
246
262
247 AddHandler(resultHandler, errorHandler, medium.InternalCancel);
263 AddHandler(resultHandler, errorHandler, medium.InternalCancel);
248
264
249 return medium;
265 return medium;
250 }
266 }
251
267
252
268
253 public Promise<T> Then(ResultHandler<T> success) {
269 public Promise<T> Then(ResultHandler<T> success) {
254 if (success == null)
270 if (success == null)
255 return this;
271 return this;
256
272
257 var medium = new Promise<T>(this, true);
273 var medium = new Promise<T>(this, true);
258
274
259 ResultHandler<T> resultHandler;
275 ResultHandler<T> resultHandler;
260
276
261 if (success != null)
277 if (success != null)
262 resultHandler = x => {
278 resultHandler = x => {
263 success(x);
279 success(x);
264 medium.Resolve(x);
280 medium.Resolve(x);
265 };
281 };
266 else
282 else
267 resultHandler = medium.Resolve;
283 resultHandler = medium.Resolve;
268
284
269 AddHandler(resultHandler, medium.Reject, medium.InternalCancel);
285 AddHandler(resultHandler, medium.Reject, medium.InternalCancel);
270
286
271 return medium;
287 return medium;
272 }
288 }
273
289
274 public Promise<T> Error(ErrorHandler error) {
290 public Promise<T> Error(ErrorHandler error) {
275 return Then(null, error);
291 return Then(null, error);
276 }
292 }
277
293
278 /// <summary>
294 /// <summary>
279 /// Handles error and allows to keep the promise.
295 /// Handles error and allows to keep the promise.
280 /// </summary>
296 /// </summary>
281 /// <remarks>
297 /// <remarks>
282 /// If the specified handler throws an exception, this exception will be used to reject the promise.
298 /// If the specified handler throws an exception, this exception will be used to reject the promise.
283 /// </remarks>
299 /// </remarks>
284 /// <param name="handler">The error handler which returns the result of the promise.</param>
300 /// <param name="handler">The error handler which returns the result of the promise.</param>
285 /// <returns>New promise.</returns>
301 /// <returns>New promise.</returns>
286 public Promise<T> Error(ErrorHandler<T> handler) {
302 public Promise<T> Error(ErrorHandler<T> handler) {
287 if (handler == null)
303 if (handler == null)
288 return this;
304 return this;
289
305
290 var medium = new Promise<T>(this, true);
306 var medium = new Promise<T>(this, true);
291
307
292 AddHandler(
308 AddHandler(
293 null,
309 null,
294 e => {
310 e => {
295 try {
311 try {
296 medium.Resolve(handler(e));
312 medium.Resolve(handler(e));
297 } catch (Exception e2) {
313 } catch (Exception e2) {
298 medium.Reject(e2);
314 medium.Reject(e2);
299 }
315 }
300 },
316 },
301 medium.InternalCancel
317 medium.InternalCancel
302 );
318 );
303
319
304 return medium;
320 return medium;
305 }
321 }
306
322
307 public Promise<T> Anyway(Action handler) {
323 public Promise<T> Anyway(Action handler) {
308 if (handler == null)
324 if (handler == null)
309 return this;
325 return this;
310
326
311 var medium = new Promise<T>();
327 var medium = new Promise<T>();
312
328
313 AddHandler(
329 AddHandler(
314 x => {
330 x => {
315 // to avoid handler being called multiple times we handle exception by ourselfs
331 // to avoid handler being called multiple times we handle exception by ourselfs
316 try {
332 try {
317 handler();
333 handler();
318 medium.Resolve(x);
334 medium.Resolve(x);
319 } catch (Exception e) {
335 } catch (Exception e) {
320 medium.Reject(e);
336 medium.Reject(e);
321 }
337 }
322 },
338 },
323
339
324 e => {
340 e => {
325 try {
341 try {
326 handler();
342 handler();
327 } catch { }
343 } catch { }
328 medium.Reject(e);
344 medium.Reject(e);
329 },
345 },
330
346
331 medium.InternalCancel
347 medium.InternalCancel
332 );
348 );
333
349
334 return medium;
350 return medium;
335 }
351 }
336
352
337 /// <summary>
353 /// <summary>
338 /// ΠŸΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ‚ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.
354 /// ΠŸΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ‚ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.
339 /// </summary>
355 /// </summary>
340 /// <typeparam name="TNew">Новый Ρ‚ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°.</typeparam>
356 /// <typeparam name="TNew">Новый Ρ‚ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°.</typeparam>
341 /// <param name="mapper">ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.</param>
357 /// <param name="mapper">ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.</param>
342 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
358 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
343 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
359 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
344 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ исходного обСщания.</returns>
360 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ исходного обСщания.</returns>
345 public Promise<TNew> Map<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler error) {
361 public Promise<TNew> Map<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler error) {
346 if (mapper == null)
362 if (mapper == null)
347 throw new ArgumentNullException("mapper");
363 throw new ArgumentNullException("mapper");
348
364
349 // создаСм ΠΏΡ€ΠΈΡ†Π΅ΠΏΠ»Π΅Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
365 // создаСм ΠΏΡ€ΠΈΡ†Π΅ΠΏΠ»Π΅Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
350 var chained = new Promise<TNew>();
366 var chained = new Promise<TNew>();
351
367
352 ResultHandler<T> resultHandler = result => chained.Resolve(mapper(result));
368 ResultHandler<T> resultHandler = result => chained.Resolve(mapper(result));
353 ErrorHandler errorHandler = delegate(Exception e) {
369 ErrorHandler errorHandler = delegate(Exception e) {
354 if (error != null)
370 if (error != null)
355 try {
371 try {
356 error(e);
372 error(e);
357 } catch { }
373 } catch { }
358 // Π² случаС ошибки Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅
374 // Π² случаС ошибки Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅
359 chained.Reject(e);
375 chained.Reject(e);
360 };
376 };
361
377
362
378
363 AddHandler(
379 AddHandler(
364 resultHandler,
380 resultHandler,
365 errorHandler,
381 errorHandler,
366 chained.InternalCancel
382 chained.InternalCancel
367 );
383 );
368
384
369 return chained;
385 return chained;
370 }
386 }
371
387
372 public Promise<TNew> Map<TNew>(ResultMapper<T, TNew> mapper) {
388 public Promise<TNew> Map<TNew>(ResultMapper<T, TNew> mapper) {
373 return Map(mapper, null);
389 return Map(mapper, null);
374 }
390 }
375
391
376 /// <summary>
392 /// <summary>
377 /// БцСпляСт нСсколько аснхронных ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ. Указанная асинхронная опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½Π° послС
393 /// БцСпляСт нСсколько аснхронных ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ. Указанная асинхронная опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½Π° послС
378 /// выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ, Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ использован для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ
394 /// выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ, Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ использован для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ
379 /// Π½ΠΎΠ²ΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.
395 /// Π½ΠΎΠ²ΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.
380 /// </summary>
396 /// </summary>
381 /// <typeparam name="TNew">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</typeparam>
397 /// <typeparam name="TNew">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</typeparam>
382 /// <param name="chained">Асинхронная опСрация, которая Π΄ΠΎΠ»ΠΆΠ½Π° Π±ΡƒΠ΄Π΅Ρ‚ Π½Π°Ρ‡Π°Ρ‚ΡŒΡΡ послС выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ.</param>
398 /// <param name="chained">Асинхронная опСрация, которая Π΄ΠΎΠ»ΠΆΠ½Π° Π±ΡƒΠ΄Π΅Ρ‚ Π½Π°Ρ‡Π°Ρ‚ΡŒΡΡ послС выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ.</param>
383 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
399 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
384 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Ρ‚Π΅ΠΊΡƒΠ΅Ρ‰ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
400 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Ρ‚Π΅ΠΊΡƒΠ΅Ρ‰ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
385 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ аснхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</returns>
401 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ аснхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</returns>
386 public Promise<TNew> Chain<TNew>(ChainedOperation<T, TNew> chained, ErrorHandler error) {
402 public Promise<TNew> Chain<TNew>(ChainedOperation<T, TNew> chained, ErrorHandler error) {
387
403
388 // ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ‚ связывания Π΅Ρ‰Π΅ Π½Π΅ Π½Π°Ρ‡Π°Ρ‚Π° асинхронная опСрация, поэтому Π½ΡƒΠΆΠ½ΠΎ
404 // ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ‚ связывания Π΅Ρ‰Π΅ Π½Π΅ Π½Π°Ρ‡Π°Ρ‚Π° асинхронная опСрация, поэтому Π½ΡƒΠΆΠ½ΠΎ
389 // ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ посрСдника, ΠΊ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠΎΠ΄Π²Ρ‹Π·ΡΠ²Π°Ρ‚ΡŒΡΡ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ.
405 // ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ посрСдника, ΠΊ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠΎΠ΄Π²Ρ‹Π·ΡΠ²Π°Ρ‚ΡŒΡΡ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ.
390 // ΠΊΠΎΠ³Π΄Π° Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° Ρ€Π΅Π°Π»ΡŒΠ½Π°Ρ асинхронная опСрация, ΠΎΠ½Π° ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ ΠΊ посрСднику, Ρ‡Ρ‚ΠΎΠ±Ρ‹
406 // ΠΊΠΎΠ³Π΄Π° Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° Ρ€Π΅Π°Π»ΡŒΠ½Π°Ρ асинхронная опСрация, ΠΎΠ½Π° ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ ΠΊ посрСднику, Ρ‡Ρ‚ΠΎΠ±Ρ‹
391 // ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· Π½Π΅Π³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Ρ€Π°Π±ΠΎΡ‚Ρ‹.
407 // ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· Π½Π΅Π³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Ρ€Π°Π±ΠΎΡ‚Ρ‹.
392 var medium = new Promise<TNew>(this, true);
408 var medium = new Promise<TNew>(this, true);
393
409
394 ResultHandler<T> resultHandler = delegate(T result) {
410 ResultHandler<T> resultHandler = delegate(T result) {
395 if (medium.IsCancelled)
411 if (medium.IsCancelled)
396 return;
412 return;
397
413
398 var promise = chained(result);
414 var promise = chained(result);
399
415
400 // notify chained operation that it's not needed
416 // notify chained operation that it's not needed
401 medium.Cancelled(() => promise.Cancel());
417 medium.Cancelled(() => promise.Cancel());
402 promise.Then(
418 promise.Then(
403 x => medium.Resolve(x),
419 x => medium.Resolve(x),
404 e => medium.Reject(e)
420 e => medium.Reject(e)
405 );
421 );
406 };
422 };
407
423
408 ErrorHandler errorHandler = delegate(Exception e) {
424 ErrorHandler errorHandler = delegate(Exception e) {
409 if (error != null)
425 if (error != null)
410 error(e);
426 error(e);
411 // Π² случаС ошибки Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅
427 // Π² случаС ошибки Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅
412 medium.Reject(e);
428 medium.Reject(e);
413 };
429 };
414
430
415 AddHandler(
431 AddHandler(
416 resultHandler,
432 resultHandler,
417 errorHandler,
433 errorHandler,
418 medium.InternalCancel
434 medium.InternalCancel
419 );
435 );
420
436
421 return medium;
437 return medium;
422 }
438 }
423
439
424 public Promise<TNew> Chain<TNew>(ChainedOperation<T, TNew> chained) {
440 public Promise<TNew> Chain<TNew>(ChainedOperation<T, TNew> chained) {
425 return Chain(chained, null);
441 return Chain(chained, null);
426 }
442 }
427
443
428 public Promise<T> Cancelled(Action handler) {
444 public Promise<T> Cancelled(Action handler) {
429 AddHandler(null, null, handler);
445 AddHandler(null, null, handler);
430 return this;
446 return this;
431 }
447 }
432
448
449 /// <summary>
450 /// Adds the specified handler for all cases (success, error, cancel)
451 /// </summary>
452 /// <param name="handler">The handler that will be called anyway</param>
453 /// <returns>self</returns>
433 public Promise<T> Finally(Action handler) {
454 public Promise<T> Finally(Action handler) {
434 if (handler == null)
455 if (handler == null)
435 throw new ArgumentNullException("handler");
456 throw new ArgumentNullException("handler");
436 AddHandler(
457 AddHandler(
437 x => handler(),
458 x => handler(),
438 e => handler(),
459 e => handler(),
439 handler
460 handler
440 );
461 );
441 return this;
462 return this;
442 }
463 }
443
464
444 /// <summary>
465 /// <summary>
445 /// ДоТидаСтся ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ³ΠΎ обСщания ΠΈ Π² случаС успСха, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚
466 /// ДоТидаСтся ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ³ΠΎ обСщания ΠΈ Π² случаС успСха, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚
446 /// Π΅Π³ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС бросаСт ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.
467 /// Π΅Π³ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС бросаСт ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.
447 /// </summary>
468 /// </summary>
448 /// <remarks>
469 /// <remarks>
449 /// <para>
470 /// <para>
450 /// Если ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ обСщания Π±Ρ‹Π»ΠΎ ΠΏΡ€Π΅Ρ€Π²Π°Π½ΠΎ ΠΏΠΎ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚Ρƒ, это Π½Π΅ Π·Π½Π°Ρ‡ΠΈΡ‚,
471 /// Если ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ обСщания Π±Ρ‹Π»ΠΎ ΠΏΡ€Π΅Ρ€Π²Π°Π½ΠΎ ΠΏΠΎ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚Ρƒ, это Π½Π΅ Π·Π½Π°Ρ‡ΠΈΡ‚,
451 /// Ρ‡Ρ‚ΠΎ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±Ρ‹Π»ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½ΠΎ ΠΈΠ»ΠΈ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π² этом Ρ€ΠΎΠ΄Π΅, это Ρ‚ΠΎΠ»ΡŒΠΊΠΎ
472 /// Ρ‡Ρ‚ΠΎ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±Ρ‹Π»ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½ΠΎ ΠΈΠ»ΠΈ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π² этом Ρ€ΠΎΠ΄Π΅, это Ρ‚ΠΎΠ»ΡŒΠΊΠΎ
452 /// ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π΅Π³ΠΎ Π½Π΅ доТдались, ΠΎΠ΄Π½Π°ΠΊΠΎ всС зарСгистрированныС
473 /// ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π΅Π³ΠΎ Π½Π΅ доТдались, ΠΎΠ΄Π½Π°ΠΊΠΎ всС зарСгистрированныС
453 /// ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, ΠΊΠ°ΠΊ Π±Ρ‹Π»ΠΈ Ρ‚Π°ΠΊ ΠΎΡΡ‚Π°Π»ΠΈΡΡŒ ΠΈ ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹, ΠΊΠΎΠ³Π΄Π°
474 /// ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, ΠΊΠ°ΠΊ Π±Ρ‹Π»ΠΈ Ρ‚Π°ΠΊ ΠΎΡΡ‚Π°Π»ΠΈΡΡŒ ΠΈ ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹, ΠΊΠΎΠ³Π΄Π°
454 /// ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
475 /// ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
455 /// </para>
476 /// </para>
456 /// <para>
477 /// <para>
457 /// Π’Π°ΠΊΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π²ΠΏΠΎΠ»Π½Π΅ ΠΎΠΏΡ€Π°Π²Π΄Π°Π½ΠΎ ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΡ‚Π΅Ρ‡ΡŒ
478 /// Π’Π°ΠΊΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π²ΠΏΠΎΠ»Π½Π΅ ΠΎΠΏΡ€Π°Π²Π΄Π°Π½ΠΎ ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΡ‚Π΅Ρ‡ΡŒ
458 /// Π² Ρ‚ΠΎΡ‚ ΠΌΠΎΠΌΠ΅Π½Ρ‚, ΠΊΠΎΠ³Π΄Π° Π½Π°Ρ‡Π°Π»Π°ΡΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ², ΠΈ
479 /// Π² Ρ‚ΠΎΡ‚ ΠΌΠΎΠΌΠ΅Π½Ρ‚, ΠΊΠΎΠ³Π΄Π° Π½Π°Ρ‡Π°Π»Π°ΡΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ², ΠΈ
459 /// ΠΊ Ρ‚ΠΎΠΌΡƒ ΠΆΠ΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡ‚ΠΎΡΡ‚ΡŒ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ ΠΈ Π΅Π³ΠΎ
480 /// ΠΊ Ρ‚ΠΎΠΌΡƒ ΠΆΠ΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡ‚ΠΎΡΡ‚ΡŒ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ ΠΈ Π΅Π³ΠΎ
460 /// ΠΎΡ‚ΠΊΠ»ΠΎΠ½Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ Π½Π΅ΠΏΡ€ΠΎΠ³Π½ΠΎΠ·ΠΈΡ€ΡƒΠ΅ΠΌΠΎΠΌΡƒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρƒ.
481 /// ΠΎΡ‚ΠΊΠ»ΠΎΠ½Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ Π½Π΅ΠΏΡ€ΠΎΠ³Π½ΠΎΠ·ΠΈΡ€ΡƒΠ΅ΠΌΠΎΠΌΡƒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρƒ.
461 /// </para>
482 /// </para>
462 /// </remarks>
483 /// </remarks>
463 /// <param name="timeout">ВрСмя оТидания</param>
484 /// <param name="timeout">ВрСмя оТидания</param>
464 /// <returns>Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния обСщания</returns>
485 /// <returns>Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния обСщания</returns>
465 public T Join(int timeout) {
486 public T Join(int timeout) {
466 var evt = new ManualResetEvent(false);
487 var evt = new ManualResetEvent(false);
467 Anyway(() => evt.Set());
488 Anyway(() => evt.Set());
468 Cancelled(() => evt.Set());
489 Cancelled(() => evt.Set());
469
490
470 if (!evt.WaitOne(timeout, true))
491 if (!evt.WaitOne(timeout, true))
471 throw new TimeoutException();
492 throw new TimeoutException();
472
493
473 switch (m_state) {
494 switch (m_state) {
474 case ResolvedState:
495 case SucceededState:
475 return m_result;
496 return m_result;
476 case CancelledState:
497 case CancelledState:
477 throw new OperationCanceledException();
498 throw new OperationCanceledException();
478 case RejectedState:
499 case RejectedState:
479 throw new TargetInvocationException(m_error);
500 throw new TargetInvocationException(m_error);
480 default:
501 default:
481 throw new ApplicationException(String.Format("Invalid promise state {0}", m_state));
502 throw new ApplicationException(String.Format("Invalid promise state {0}", m_state));
482 }
503 }
483 }
504 }
484
505
485 public T Join() {
506 public T Join() {
486 return Join(Timeout.Infinite);
507 return Join(Timeout.Infinite);
487 }
508 }
488
509
489 void AddHandler(ResultHandler<T> success, ErrorHandler error, Action cancel) {
510 void AddHandler(ResultHandler<T> success, ErrorHandler error, Action cancel) {
490 Interlocked.Increment(ref m_childrenCount);
511 Interlocked.Increment(ref m_childrenCount);
491
512
492 HandlerDescriptor handler = new HandlerDescriptor {
513 HandlerDescriptor handler = new HandlerDescriptor {
493 resultHandler = success,
514 resultHandler = success,
494 errorHandler = error,
515 errorHandler = error,
495 cancellHandler = cancel
516 cancellHandler = cancel
496 };
517 };
497
518
498 bool queued;
519 bool queued;
499
520
500 if (!IsResolved) {
521 if (!IsResolved) {
501 m_handlers.Enqueue(handler);
522 m_handlers.Enqueue(handler);
502 queued = true;
523 queued = true;
503 } else {
524 } else {
504 // the promise is in resolved state, just invoke the handled with minimum overhead
525 // the promise is in resolved state, just invoke the handled with minimum overhead
505 queued = false;
526 queued = false;
506 InvokeHandler(handler);
527 InvokeHandler(handler);
507 }
528 }
508
529
509 if (queued && IsResolved && m_handlers.TryDequeue(out handler))
530 if (queued && IsResolved && m_handlers.TryDequeue(out handler))
510 // if the promise have been resolved while we was adding handler to the queue
531 // if the promise have been resolved while we was adding handler to the queue
511 // we can't guarantee that someone is still processing it
532 // we can't guarantee that someone is still processing it
512 // therefore we will fetch a handler from the queue and execute it
533 // therefore we will fetch a handler from the queue and execute it
513 // note that fetched handler may be not the one we have added
534 // note that fetched handler may be not the one we have added
514 InvokeHandler(handler);
535 InvokeHandler(handler);
515
536
516 }
537 }
517
538
518 void InvokeHandler(HandlerDescriptor handler) {
539 void InvokeHandler(HandlerDescriptor handler) {
519 switch (m_state) {
540 switch (m_state) {
520 case ResolvedState:
541 case SucceededState:
521 handler.Resolve(m_result);
542 handler.Resolve(m_result);
522 break;
543 break;
523 case RejectedState:
544 case RejectedState:
524 handler.Reject(m_error);
545 handler.Reject(m_error);
525 break;
546 break;
526 case CancelledState:
547 case CancelledState:
527 handler.Cancel();
548 handler.Cancel();
528 break;
549 break;
529 default:
550 default:
530 // do nothing
551 // do nothing
531 return;
552 return;
532 }
553 }
533 }
554 }
534
555
535 protected virtual void OnStateChanged() {
556 protected virtual void OnStateChanged() {
536 HandlerDescriptor handler;
557 HandlerDescriptor handler;
537 while (m_handlers.TryDequeue(out handler))
558 while (m_handlers.TryDequeue(out handler))
538 InvokeHandler(handler);
559 InvokeHandler(handler);
539 }
560 }
540
561
541
542
543 public bool IsExclusive {
562 public bool IsExclusive {
544 get {
563 get {
545 return m_childrenCount <= 1;
564 return m_childrenCount <= 1;
546 }
565 }
547 }
566 }
548
567
549 protected bool Cancel(bool dependencies) {
568 protected bool Cancel(bool dependencies) {
550 if (BeginTransit()) {
569 if (BeginTransit()) {
551 CompleteTransit(CancelledState);
570 CompleteTransit(CancelledState);
552 OnStateChanged();
571 OnStateChanged();
553
572
554 if (dependencies && m_parent != null && m_parent.IsExclusive)
573 if (dependencies && m_parent != null && m_parent.IsExclusive)
555 m_parent.Cancel();
574 m_parent.Cancel();
556
575
557 return true;
576 return true;
558 } else {
577 } else {
559 return false;
578 return false;
560 }
579 }
561 }
580 }
562
581
582 /// <summary>
583 /// ΠžΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ нСсколько ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ являСтся массив Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
584 /// Если хотябы ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚ΠΎ Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ Ρ‚ΠΎΠΆΠ΅ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
585 /// ΠŸΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ Π½ΠΎΠ²ΠΎΠ³ΠΎ обСщания, ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅ обСщания Ρ‚Π°ΠΊΠΆΠ΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Ρ‹, Ссли Π½ΠΈΠΊΡ‚ΠΎ большС Π½Π° Π½ΠΈΡ… Π½Π΅ подписан.
586 /// </summary>
587 /// <param name="promises">Бписок ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ. Если список пустой, Ρ‚ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ возвращаСтся ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹ΠΌ.</param>
588 /// <returns>ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰Π΅Π΅ Π² сСбС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.</returns>
589 /// <exception cref="ArgumentNullException"><paramref name="promises"/> Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ null</exception>
590 public static Promise<T[]> CreateComposite(IList<Promise<T>> promises) {
591 if (promises == null)
592 throw new ArgumentNullException();
593
594 // создаСм аккумулятор для Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² ΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
595 var result = new T[promises.Count];
596 var promise = new Promise<T[]>();
597
598 // special case
599 if (promises.Count == 0) {
600 promise.Resolve(result);
601 return promise;
602 }
603
604 int pending = promises.Count;
605
606 for (int i = 0; i < promises.Count; i++) {
607 var dest = i;
608
609 promises[i].Then(
610 x => {
611 result[dest] = x;
612 if(Interlocked.Decrement(ref pending) == 0)
613 promise.Resolve(result);
614 },
615 e => promise.Reject(e)
616 );
617 }
618
619 promise.Cancelled(
620 () => {
621 foreach(var d in promises)
622 if(d.IsExclusive)
623 d.Cancel();
624 }
625 );
626
627 return promise;
628 }
629
630 public static Promise<T> ResultToPromise(T result) {
631 var p = new Promise<T>();
632 p.Resolve(result);
633 return p;
634 }
635
636 public static Promise<T> ExceptionToPromise(Exception error) {
637 if (error == null)
638 throw new ArgumentNullException();
639
640 var p = new Promise<T>();
641 p.Reject(error);
642 return p;
643 }
644
563 }
645 }
564 }
646 }
@@ -1,132 +1,140
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
3 using System.Linq;
4 using System.Text;
4 using System.Text;
5 using System.Threading;
5 using System.Threading;
6
6
7 namespace Implab
7 namespace Implab
8 {
8 {
9 /// <summary>
9 /// <summary>
10 /// This class allows to interact with asyncronuos task.
10 /// This class allows to interact with asyncronuos task.
11 /// </summary>
11 /// </summary>
12 /// <remarks>
12 /// <remarks>
13 /// Members of this object are thread safe.
13 /// Members of this object are thread safe.
14 /// </remarks>
14 /// </remarks>
15 class TaskController: IProgressNotifier, ITaskController, ICancellable
15 public class TaskController: IProgressNotifier, ITaskController
16 {
16 {
17 readonly object m_lock;
17 readonly object m_lock;
18 string m_message;
18 string m_message;
19
19
20 float m_current;
20 float m_current;
21 float m_max;
21 float m_max;
22
22
23 bool m_cancelled;
23 bool m_cancelled;
24
24
25 public event EventHandler Cancelled;
25 public event EventHandler<ValueEventArgs<string>> MessageUpdated;
26 public event EventHandler<ValueEventArgs<string>> MessageUpdated;
26 public event EventHandler<ValueEventArgs<float>> ProgressUpdated;
27 public event EventHandler<ValueEventArgs<float>> ProgressUpdated;
27 public event EventHandler<ProgressInitEventArgs> ProgressInit;
28 public event EventHandler<ProgressInitEventArgs> ProgressInit;
28
29
29 public TaskController()
30 public TaskController()
30 {
31 {
31 m_lock = new Object();
32 m_lock = new Object();
32 }
33 }
33
34
34 public string Message
35 public string Message
35 {
36 {
36 get
37 get
37 {
38 {
38 lock (m_lock)
39 lock (m_lock)
39 return m_message;
40 return m_message;
40 }
41 }
41 set
42 set
42 {
43 {
43 lock (m_lock)
44 lock (m_lock)
44 {
45 {
45 m_message = value;
46 m_message = value;
46 OnMessageUpdated();
47 OnMessageUpdated();
47 }
48 }
48 }
49 }
49 }
50 }
50
51
51 public float CurrentProgress
52 public float CurrentProgress
52 {
53 {
53 get
54 get
54 {
55 {
55 lock (m_lock)
56 lock (m_lock)
56 return m_current;
57 return m_current;
57 }
58 }
58 set
59 set
59 {
60 {
60 lock (m_lock)
61 lock (m_lock)
61 {
62 {
62 var prev = m_current;
63 var prev = m_current;
63 m_current = value;
64 m_current = value;
64 if (m_current >= m_max)
65 if (m_current >= m_max)
65 m_current = m_max;
66 m_current = m_max;
66 if (m_current != prev)
67 if (m_current != prev)
67 OnProgressUpdated();
68 OnProgressUpdated();
68 }
69 }
69 }
70 }
70 }
71 }
71
72
72 public void InitProgress(float current, float max, string message)
73 public void InitProgress(float current, float max, string message)
73 {
74 {
74 if (max < 0)
75 if (max < 0)
75 throw new ArgumentOutOfRangeException("max");
76 throw new ArgumentOutOfRangeException("max");
76 if (current < 0 || current > max)
77 if (current < 0 || current > max)
77 throw new ArgumentOutOfRangeException("current");
78 throw new ArgumentOutOfRangeException("current");
78
79
79 lock(m_lock) {
80 lock(m_lock) {
80 m_current = current;
81 m_current = current;
81 m_max = max;
82 m_max = max;
82 m_message = message;
83 m_message = message;
83 OnProgressInit();
84 OnProgressInit();
84 }
85 }
85 }
86 }
86
87
87 public bool Cancelled {
88 public bool IsCancelled {
88 get {
89 get {
89 lock (m_lock)
90 lock (m_lock)
90 return m_cancelled;
91 return m_cancelled;
91 }
92 }
92 }
93 }
93
94
94 public bool Cancel() {
95 public bool Cancel() {
95 lock (m_lock) {
96 lock (m_lock) {
96 if (!m_cancelled) {
97 if (!m_cancelled) {
97 m_cancelled = true;
98 m_cancelled = true;
98 return true;
99 return true;
99 } else {
100 } else {
100 return false;
101 return false;
101 }
102 }
102 }
103 }
103 }
104 }
104
105
106 protected virtual void OnCancelled() {
107 var temp = Cancelled;
108 if (temp != null) {
109 temp(this,new EventArgs());
110 }
111 }
112
105 protected virtual void OnMessageUpdated()
113 protected virtual void OnMessageUpdated()
106 {
114 {
107 var temp = MessageUpdated;
115 var temp = MessageUpdated;
108 if (temp != null)
116 if (temp != null)
109 {
117 {
110 temp(this, new ValueEventArgs<string>(m_message));
118 temp(this, new ValueEventArgs<string>(m_message));
111 }
119 }
112 }
120 }
113
121
114 protected virtual void OnProgressUpdated()
122 protected virtual void OnProgressUpdated()
115 {
123 {
116 var temp = ProgressUpdated;
124 var temp = ProgressUpdated;
117 if (temp != null)
125 if (temp != null)
118 {
126 {
119 temp(this,new ValueEventArgs<float>(m_current));
127 temp(this,new ValueEventArgs<float>(m_current));
120 }
128 }
121 }
129 }
122
130
123 protected virtual void OnProgressInit()
131 protected virtual void OnProgressInit()
124 {
132 {
125 var temp = ProgressInit;
133 var temp = ProgressInit;
126 if (temp != null)
134 if (temp != null)
127 {
135 {
128 temp(this, new ProgressInitEventArgs(m_current,m_max, m_message));
136 temp(this, new ProgressInitEventArgs(m_current,m_max, m_message));
129 }
137 }
130 }
138 }
131 }
139 }
132 }
140 }
General Comments 0
You need to be logged in to leave comments. Login now