##// END OF EJS Templates
renamed Promise.Last -> Promise.On...
cin -
r104:5f10d54b45df v2
parent child
Show More
@@ -0,0 +1,19
1 using System;
2
3 namespace Implab {
4 [Flags]
5 public enum PromiseEventType {
6 Success = 1,
7 Error = 2,
8 Cancelled = 4,
9 /// <summary>
10 /// Π—Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΎ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ, Π»ΠΈΠ±ΠΎ Π²ΠΎΠ·Π½ΠΈΠΊΠ»Π° ошибка,
11 /// </summary>
12 All = 7,
13 /// <summary>
14 /// Π—Π°Π²Ρ€Π΅ΡˆΠ΅Π½ΠΎ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ, Π»ΠΈΠ±ΠΎ Π²ΠΎΠ·Π½ΠΈΠΊΠ»Π° ошибка.
15 /// </summary>
16 Complete = 3
17 }
18 }
19
@@ -1,41 +1,41
1 1 using System;
2 2 using System.Windows.Forms;
3 3 using System.Threading;
4 4
5 5 namespace Implab.Fx
6 6 {
7 7 public static class PromiseHelpers
8 8 {
9 9 /// <summary>
10 10 /// ΠŸΠ΅Ρ€Π΅Π½Π°ΠΏΡ€Π°Π²Π»ΡΠ΅Ρ‚ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ обСщания Π² ΠΏΠΎΡ‚ΠΎΠΊ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠ³ΠΎ элСмСнта управлСния.
11 11 /// </summary>
12 12 /// <typeparam name="T">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° обСщания</typeparam>
13 13 /// <param name="that">Π˜ΡΡ…ΠΎΠ΄Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅</param>
14 14 /// <param name="ctl">Π­Π»Π΅ΠΌΠ΅Π½Ρ‚ управлСния</param>
15 15 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Ρ‹ Π² ΠΏΠΎΡ‚ΠΎΠΊΠ΅ элСмСнта управлСния.</returns>
16 16 /// <exception cref="ArgumentNullException">ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ <c>null</c>.</exception>
17 17 /// <example>
18 18 /// client
19 19 /// .Get("description.txt") // returns a promise
20 20 /// .DispatchToControl(m_ctl) // handle the promise in the thread of the control
21 21 /// .Then(
22 22 /// description => m_ctl.Text = description // now it's safe
23 23 /// )
24 24 /// </example>
25 25 public static IPromise<T> DispatchToControl<T>(this IPromise<T> that, Control ctl)
26 26 {
27 27 Safe.ArgumentNotNull(that, "that");
28 28 Safe.ArgumentNotNull(ctl, "ctl");
29 29
30 30 var directed = new ControlBoundPromise<T>(ctl,that);
31 31
32 that.Last(
32 that.On(
33 33 directed.Resolve,
34 34 directed.Reject,
35 35 directed.Cancel
36 36 );
37 37
38 38 return directed;
39 39 }
40 40 }
41 41 }
@@ -1,86 +1,87
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.Linq;
4 4 using System.Text;
5 5
6 6 namespace Implab {
7 7 public interface IPromise: ICancellable {
8 8 /// <summary>
9 9 /// Check whereather the promise has no more than one dependent promise.
10 10 /// </summary>
11 11 bool IsExclusive {
12 12 get;
13 13 }
14 14
15 15 /// <summary>
16 16 /// Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌΠΎΠ³ΠΎ Ρ‡Π΅Ρ€Π΅Π· Π΄Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅.
17 17 /// </summary>
18 18 Type PromiseType { get; }
19 19
20 20 /// <summary>
21 21 /// ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ являСтся Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Ρ‹ΠΌ, Π»ΠΈΠ±ΠΎ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ, Π»ΠΈΠ±ΠΎ с ошибкой, Π»ΠΈΠ±ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½ΠΎ.
22 22 /// </summary>
23 23 bool IsResolved { get; }
24 24
25 25 /// <summary>
26 26 /// ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±Ρ‹Π»ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½ΠΎ.
27 27 /// </summary>
28 28 bool IsCancelled { get; }
29 29
30 30 IPromise Then(Action success, Action<Exception> error, Action cancel);
31 31 IPromise Then(Action success, Action<Exception> error);
32 32 IPromise Then(Action success);
33 33
34 34 IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Action cancel);
35 35 IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error);
36 36 IPromise Chain(Func<IPromise> chained);
37 37
38 38 /// <summary>
39 39 /// ДобавляСт послСднй ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ, Π½Π΅ создаСт ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
40 40 /// </summary>
41 41 /// <param name="success">Success.</param>
42 42 /// <param name="error">Error.</param>
43 43 /// <param name="cancel">Cancel.</param>
44 void Last(Action success, Action<Exception> error, Action cancel);
45 void Last(Action success, Action<Exception> error);
46 void Last(Action success);
44 void On(Action success, Action<Exception> error, Action cancel);
45 void On(Action success, Action<Exception> error);
46 void On(Action success);
47 void On(Action success, PromiseEventType events);
47 48
48 49 IPromise Error(Action<Exception> error);
49 50 /// <summary>
50 51 /// ΠžΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ Π»ΠΈΠ±ΠΎ ΠΎΡˆΠΈΠ±ΠΊΡƒ, Π»ΠΈΠ±ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Π»ΠΈΠ±ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Ρƒ.
51 52 /// </summary>
52 53 /// <param name="handler">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ.</param>
53 54 /// <remarks>ПослС ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ ошибки, ΠΎΠ½Π° пСрСдаСтся дальшС.</remarks>
54 55 /// <summary>
55 56 /// ΠžΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ Π»ΠΈΠ±ΠΎ ΠΎΡˆΠΈΠ±ΠΊΡƒ, Π»ΠΈΠ±ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Π»ΠΈΠ±ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Ρƒ обСщания.
56 57 /// </summary>
57 58 /// <param name="handler">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ.</param>
58 59 /// <remarks>ПослС ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ ошибки, ΠΎΠ½Π° пСрСдаСтся дальшС.</remarks>
59 60 IPromise Anyway(Action handler);
60 61 /// <summary>
61 62 /// ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ для рСгистрации ΠΎΡ‚ΠΌΠ΅Π½Ρ‹ обСщания.
62 63 /// </summary>
63 64 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, связанноС с Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΌ, выполнится послС ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠ³ΠΎ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ°.</returns>
64 65 /// <param name="handler">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ события.</param>
65 66 /// <remarks>Если ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, Ρ‚ΠΎ ΠΎΠ½ΠΎ пСрСдаСтся ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΡƒ ошибки, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ€Π°Π±ΠΎΡ‚Ρ‹
66 67 /// ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½ связанному ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΡŽ</remarks>
67 68 IPromise Cancelled(Action handler);
68 69
69 70 /// <summary>
70 71 /// ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ обСщания ΠΊ Π·Π°Π΄Π°Π½Π½ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅.
71 72 /// </summary>
72 73 IPromise<T> Cast<T>();
73 74
74 75 /// <summary>
75 76 /// Π‘ΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ с ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ΠΌ.
76 77 /// </summary>
77 78 void Join();
78 79 /// <summary>
79 80 /// Π‘ΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ с ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ΠΌ.
80 81 /// </summary>
81 82 /// <param name="timeout">ВрСмя оТидания, ΠΏΠΎ Π΅Π³ΠΎ ΠΈΡΡ‚Π΅Ρ‡Π΅Π½ΠΈΡŽ Π²ΠΎΠ·Π½ΠΈΠΊΠ½Π΅Ρ‚ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.</param>
82 83 /// <exception cref="TimeoutException">ΠŸΡ€Π΅Π²Ρ‹ΡˆΠ΅Π½ΠΎ врСмя оТидания.</exception>
83 84 void Join(int timeout);
84 85
85 86 }
86 87 }
@@ -1,40 +1,40
1 1 using System;
2 2
3 3 namespace Implab {
4 4 public interface IPromise<T> : IPromise {
5 5
6 6 new T Join();
7 7
8 8 new T Join(int timeout);
9 9
10 void Last(Action<T> success, Action<Exception> error, Action cancel);
10 void On(Action<T> success, Action<Exception> error, Action cancel);
11 11
12 void Last(Action<T> success, Action<Exception> error);
12 void On(Action<T> success, Action<Exception> error);
13 13
14 void Last(Action<T> success);
14 void On(Action<T> success);
15 15
16 16 IPromise<T> Then(Action<T> success, Func<Exception,T> error, Action cancel);
17 17
18 18 IPromise<T> Then(Action<T> success, Func<Exception,T> error);
19 19
20 20 IPromise<T> Then(Action<T> success);
21 21
22 22 IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception,T2> error, Action cancel);
23 23
24 24 IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception,T2> error);
25 25
26 26 IPromise<T2> Then<T2>(Func<T, T2> mapper);
27 27
28 28 IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception,IPromise<T2>> error, Action cancel);
29 29
30 30 IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception,IPromise<T2>> error);
31 31
32 32 IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained);
33 33
34 34 IPromise<T> Error(Func<Exception,T> error);
35 35
36 36 new IPromise<T> Cancelled(Action handler);
37 37
38 38 new IPromise<T> Anyway(Action handler);
39 39 }
40 40 }
@@ -1,222 +1,223
1 1 ο»Ώ<?xml version="1.0" encoding="utf-8"?>
2 2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 3 <PropertyGroup>
4 4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5 5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6 6 <ProjectGuid>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</ProjectGuid>
7 7 <OutputType>Library</OutputType>
8 8 <RootNamespace>Implab</RootNamespace>
9 9 <AssemblyName>Implab</AssemblyName>
10 10 </PropertyGroup>
11 11 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
12 12 <DebugSymbols>true</DebugSymbols>
13 13 <DebugType>full</DebugType>
14 14 <Optimize>false</Optimize>
15 15 <OutputPath>bin\Debug</OutputPath>
16 16 <DefineConstants>TRACE;DEBUG;</DefineConstants>
17 17 <ErrorReport>prompt</ErrorReport>
18 18 <WarningLevel>4</WarningLevel>
19 19 <ConsolePause>false</ConsolePause>
20 20 <RunCodeAnalysis>true</RunCodeAnalysis>
21 21 </PropertyGroup>
22 22 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
23 23 <DebugType>full</DebugType>
24 24 <Optimize>true</Optimize>
25 25 <OutputPath>bin\Release</OutputPath>
26 26 <ErrorReport>prompt</ErrorReport>
27 27 <WarningLevel>4</WarningLevel>
28 28 <ConsolePause>false</ConsolePause>
29 29 </PropertyGroup>
30 30 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' ">
31 31 <DebugSymbols>true</DebugSymbols>
32 32 <DebugType>full</DebugType>
33 33 <Optimize>false</Optimize>
34 34 <OutputPath>bin\Debug</OutputPath>
35 35 <DefineConstants>TRACE;DEBUG;NET_4_5</DefineConstants>
36 36 <ErrorReport>prompt</ErrorReport>
37 37 <WarningLevel>4</WarningLevel>
38 38 <RunCodeAnalysis>true</RunCodeAnalysis>
39 39 <ConsolePause>false</ConsolePause>
40 40 </PropertyGroup>
41 41 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' ">
42 42 <Optimize>true</Optimize>
43 43 <OutputPath>bin\Release</OutputPath>
44 44 <ErrorReport>prompt</ErrorReport>
45 45 <WarningLevel>4</WarningLevel>
46 46 <ConsolePause>false</ConsolePause>
47 47 <DefineConstants>NET_4_5</DefineConstants>
48 48 </PropertyGroup>
49 49 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugMono|AnyCPU' ">
50 50 <DebugSymbols>true</DebugSymbols>
51 51 <DebugType>full</DebugType>
52 52 <Optimize>false</Optimize>
53 53 <OutputPath>bin\Debug</OutputPath>
54 54 <DefineConstants>TRACE;DEBUG;NET_4_5;MONO</DefineConstants>
55 55 <ErrorReport>prompt</ErrorReport>
56 56 <WarningLevel>4</WarningLevel>
57 57 <RunCodeAnalysis>true</RunCodeAnalysis>
58 58 <ConsolePause>false</ConsolePause>
59 59 </PropertyGroup>
60 60 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseMono|AnyCPU' ">
61 61 <Optimize>true</Optimize>
62 62 <OutputPath>bin\Release</OutputPath>
63 63 <DefineConstants>NET_4_5;MONO;</DefineConstants>
64 64 <ErrorReport>prompt</ErrorReport>
65 65 <WarningLevel>4</WarningLevel>
66 66 <ConsolePause>false</ConsolePause>
67 67 </PropertyGroup>
68 68 <ItemGroup>
69 69 <Reference Include="System" />
70 70 <Reference Include="System.Xml" />
71 71 </ItemGroup>
72 72 <ItemGroup>
73 73 <Compile Include="Component.cs" />
74 74 <Compile Include="CustomEqualityComparer.cs" />
75 75 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
76 76 <Compile Include="Diagnostics\EventText.cs" />
77 77 <Compile Include="Diagnostics\IEventTextFormatter.cs" />
78 78 <Compile Include="Diagnostics\LogChannel.cs" />
79 79 <Compile Include="Diagnostics\LogicalOperation.cs" />
80 80 <Compile Include="Diagnostics\TextFileListener.cs" />
81 81 <Compile Include="Diagnostics\TextListenerBase.cs" />
82 82 <Compile Include="Diagnostics\TraceLog.cs" />
83 83 <Compile Include="Diagnostics\TraceEvent.cs" />
84 84 <Compile Include="Diagnostics\TraceEventType.cs" />
85 85 <Compile Include="Disposable.cs" />
86 86 <Compile Include="ICancellable.cs" />
87 87 <Compile Include="IProgressHandler.cs" />
88 88 <Compile Include="IProgressNotifier.cs" />
89 89 <Compile Include="IPromiseT.cs" />
90 90 <Compile Include="IPromise.cs" />
91 91 <Compile Include="IServiceLocator.cs" />
92 92 <Compile Include="ITaskController.cs" />
93 93 <Compile Include="JSON\JSONElementContext.cs" />
94 94 <Compile Include="JSON\JSONElementType.cs" />
95 95 <Compile Include="JSON\JSONGrammar.cs" />
96 96 <Compile Include="JSON\JSONParser.cs" />
97 97 <Compile Include="JSON\JSONScanner.cs" />
98 98 <Compile Include="JSON\JsonTokenType.cs" />
99 99 <Compile Include="JSON\JSONWriter.cs" />
100 100 <Compile Include="JSON\JSONXmlReader.cs" />
101 101 <Compile Include="JSON\JSONXmlReaderOptions.cs" />
102 102 <Compile Include="JSON\StringTranslator.cs" />
103 103 <Compile Include="Parallels\DispatchPool.cs" />
104 104 <Compile Include="Parallels\ArrayTraits.cs" />
105 105 <Compile Include="Parallels\MTQueue.cs" />
106 106 <Compile Include="Parallels\WorkerPool.cs" />
107 107 <Compile Include="Parsing\Alphabet.cs" />
108 108 <Compile Include="Parsing\AlphabetBase.cs" />
109 109 <Compile Include="Parsing\AltToken.cs" />
110 110 <Compile Include="Parsing\BinaryToken.cs" />
111 111 <Compile Include="Parsing\CatToken.cs" />
112 112 <Compile Include="Parsing\CDFADefinition.cs" />
113 113 <Compile Include="Parsing\DFABuilder.cs" />
114 114 <Compile Include="Parsing\DFADefinitionBase.cs" />
115 115 <Compile Include="Parsing\DFAStateDescriptor.cs" />
116 116 <Compile Include="Parsing\DFAutomaton.cs" />
117 117 <Compile Include="Parsing\EDFADefinition.cs" />
118 118 <Compile Include="Parsing\EmptyToken.cs" />
119 119 <Compile Include="Parsing\EndToken.cs" />
120 120 <Compile Include="Parsing\EnumAlphabet.cs" />
121 121 <Compile Include="Parsing\Grammar.cs" />
122 122 <Compile Include="Parsing\IAlphabet.cs" />
123 123 <Compile Include="Parsing\IDFADefinition.cs" />
124 124 <Compile Include="Parsing\IVisitor.cs" />
125 125 <Compile Include="Parsing\ParserException.cs" />
126 126 <Compile Include="Parsing\Scanner.cs" />
127 127 <Compile Include="Parsing\StarToken.cs" />
128 128 <Compile Include="Parsing\SymbolToken.cs" />
129 129 <Compile Include="Parsing\Token.cs" />
130 130 <Compile Include="SafePool.cs" />
131 131 <Compile Include="ServiceLocator.cs" />
132 132 <Compile Include="TaskController.cs" />
133 133 <Compile Include="ProgressInitEventArgs.cs" />
134 134 <Compile Include="Properties\AssemblyInfo.cs" />
135 135 <Compile Include="Promise.cs" />
136 136 <Compile Include="Parallels\AsyncPool.cs" />
137 137 <Compile Include="Safe.cs" />
138 138 <Compile Include="ValueEventArgs.cs" />
139 139 <Compile Include="PromiseExtensions.cs" />
140 140 <Compile Include="TransientPromiseException.cs" />
141 141 <Compile Include="SyncContextPromise.cs" />
142 142 <Compile Include="ObjectPool.cs" />
143 143 <Compile Include="Diagnostics\OperationContext.cs" />
144 144 <Compile Include="Diagnostics\TraceContext.cs" />
145 145 <Compile Include="Diagnostics\LogEventArgs.cs" />
146 146 <Compile Include="Diagnostics\LogEventArgsT.cs" />
147 147 <Compile Include="Diagnostics\Extensions.cs" />
148 148 <Compile Include="IComponentContainer.cs" />
149 149 <Compile Include="MTComponentContainer.cs" />
150 <Compile Include="PromiseEventType.cs" />
150 151 </ItemGroup>
151 152 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
152 153 <ItemGroup />
153 154 <ProjectExtensions>
154 155 <MonoDevelop>
155 156 <Properties>
156 157 <Policies>
157 158 <CSharpFormattingPolicy IndentSwitchBody="True" NamespaceBraceStyle="EndOfLine" ClassBraceStyle="EndOfLine" InterfaceBraceStyle="EndOfLine" StructBraceStyle="EndOfLine" EnumBraceStyle="EndOfLine" MethodBraceStyle="EndOfLine" ConstructorBraceStyle="EndOfLine" DestructorBraceStyle="EndOfLine" BeforeMethodDeclarationParentheses="False" BeforeMethodCallParentheses="False" BeforeConstructorDeclarationParentheses="False" NewLineBeforeConstructorInitializerColon="NewLine" NewLineAfterConstructorInitializerColon="SameLine" BeforeIndexerDeclarationBracket="False" BeforeDelegateDeclarationParentheses="False" NewParentheses="False" SpacesBeforeBrackets="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
158 159 <TextStylePolicy FileWidth="120" EolMarker="Unix" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
159 160 <DotNetNamingPolicy DirectoryNamespaceAssociation="PrefixedHierarchical" ResourceNamePolicy="MSBuild" />
160 161 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="application/xml" />
161 162 <XmlFormattingPolicy inheritsSet="Mono" inheritsScope="application/xml" scope="application/xml" />
162 163 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" />
163 164 <NameConventionPolicy>
164 165 <Rules>
165 166 <NamingRule Name="Namespaces" AffectedEntity="Namespace" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
166 167 <NamingRule Name="Types" AffectedEntity="Class, Struct, Enum, Delegate" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
167 168 <NamingRule Name="Interfaces" AffectedEntity="Interface" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
168 169 <RequiredPrefixes>
169 170 <String>I</String>
170 171 </RequiredPrefixes>
171 172 </NamingRule>
172 173 <NamingRule Name="Attributes" AffectedEntity="CustomAttributes" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
173 174 <RequiredSuffixes>
174 175 <String>Attribute</String>
175 176 </RequiredSuffixes>
176 177 </NamingRule>
177 178 <NamingRule Name="Event Arguments" AffectedEntity="CustomEventArgs" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
178 179 <RequiredSuffixes>
179 180 <String>EventArgs</String>
180 181 </RequiredSuffixes>
181 182 </NamingRule>
182 183 <NamingRule Name="Exceptions" AffectedEntity="CustomExceptions" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
183 184 <RequiredSuffixes>
184 185 <String>Exception</String>
185 186 </RequiredSuffixes>
186 187 </NamingRule>
187 188 <NamingRule Name="Methods" AffectedEntity="Methods" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
188 189 <NamingRule Name="Static Readonly Fields" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Protected, Public" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True" />
189 190 <NamingRule Name="Fields (Non Private)" AffectedEntity="Field" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
190 191 <NamingRule Name="ReadOnly Fields (Non Private)" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False" />
191 192 <NamingRule Name="Fields (Private)" AffectedEntity="Field, ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
192 193 <RequiredPrefixes>
193 194 <String>m_</String>
194 195 </RequiredPrefixes>
195 196 </NamingRule>
196 197 <NamingRule Name="Static Fields (Private)" AffectedEntity="Field" VisibilityMask="Private" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True">
197 198 <RequiredPrefixes>
198 199 <String>_</String>
199 200 </RequiredPrefixes>
200 201 </NamingRule>
201 202 <NamingRule Name="ReadOnly Fields (Private)" AffectedEntity="ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
202 203 <RequiredPrefixes>
203 204 <String>m_</String>
204 205 </RequiredPrefixes>
205 206 </NamingRule>
206 207 <NamingRule Name="Constant Fields" AffectedEntity="ConstantField" VisibilityMask="VisibilityMask" NamingStyle="AllUpper" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
207 208 <NamingRule Name="Properties" AffectedEntity="Property" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
208 209 <NamingRule Name="Events" AffectedEntity="Event" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
209 210 <NamingRule Name="Enum Members" AffectedEntity="EnumMember" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
210 211 <NamingRule Name="Parameters" AffectedEntity="Parameter, LocalVariable" VisibilityMask="VisibilityMask" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
211 212 <NamingRule Name="Type Parameters" AffectedEntity="TypeParameter" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
212 213 <RequiredPrefixes>
213 214 <String>T</String>
214 215 </RequiredPrefixes>
215 216 </NamingRule>
216 217 </Rules>
217 218 </NameConventionPolicy>
218 219 </Policies>
219 220 </Properties>
220 221 </MonoDevelop>
221 222 </ProjectExtensions>
222 223 </Project> No newline at end of file
@@ -1,207 +1,207
1 1 using Implab.Diagnostics;
2 2 using System;
3 3 using System.Diagnostics;
4 4 using System.Threading;
5 5
6 6 namespace Implab.Parallels {
7 7 public static class ArrayTraits {
8 8 class ArrayIterator<TSrc> : DispatchPool<int> {
9 9 readonly Action<TSrc> m_action;
10 10 readonly TSrc[] m_source;
11 11 readonly Promise<int> m_promise = new Promise<int>();
12 12 readonly LogicalOperation m_logicalOperation;
13 13
14 14 int m_pending;
15 15 int m_next;
16 16
17 17 public ArrayIterator(TSrc[] source, Action<TSrc> action, int threads)
18 18 : base(threads) {
19 19
20 20 Debug.Assert(source != null);
21 21 Debug.Assert(action != null);
22 22
23 23 m_logicalOperation = TraceContext.Instance.CurrentOperation;
24 24 m_next = 0;
25 25 m_source = source;
26 26 m_pending = source.Length;
27 27 m_action = action;
28 28
29 29 m_promise.Anyway(Dispose);
30 30
31 31 InitPool();
32 32 }
33 33
34 34 public Promise<int> Promise {
35 35 get {
36 36 return m_promise;
37 37 }
38 38 }
39 39
40 40 protected override void Worker() {
41 41 TraceContext.Instance.EnterLogicalOperation(m_logicalOperation, false);
42 42 try {
43 43 base.Worker();
44 44 } finally {
45 45 TraceContext.Instance.Leave();
46 46 }
47 47 }
48 48
49 49 protected override bool TryDequeue(out int unit) {
50 50 unit = Interlocked.Increment(ref m_next) - 1;
51 51 return unit < m_source.Length;
52 52 }
53 53
54 54 protected override void InvokeUnit(int unit) {
55 55 try {
56 56 m_action(m_source[unit]);
57 57 var pending = Interlocked.Decrement(ref m_pending);
58 58 if (pending == 0)
59 59 m_promise.Resolve(m_source.Length);
60 60 } catch (Exception e) {
61 61 m_promise.Reject(e);
62 62 }
63 63 }
64 64 }
65 65
66 66 class ArrayMapper<TSrc, TDst>: DispatchPool<int> {
67 67 readonly Func<TSrc, TDst> m_transform;
68 68 readonly TSrc[] m_source;
69 69 readonly TDst[] m_dest;
70 70 readonly Promise<TDst[]> m_promise = new Promise<TDst[]>();
71 71 readonly LogicalOperation m_logicalOperation;
72 72
73 73 int m_pending;
74 74 int m_next;
75 75
76 76 public ArrayMapper(TSrc[] source, Func<TSrc, TDst> transform, int threads)
77 77 : base(threads) {
78 78
79 79 Debug.Assert (source != null);
80 80 Debug.Assert( transform != null);
81 81
82 82 m_next = 0;
83 83 m_source = source;
84 84 m_dest = new TDst[source.Length];
85 85 m_pending = source.Length;
86 86 m_transform = transform;
87 87 m_logicalOperation = TraceContext.Instance.CurrentOperation;
88 88
89 89 m_promise.Anyway(Dispose);
90 90
91 91 InitPool();
92 92 }
93 93
94 94 public Promise<TDst[]> Promise {
95 95 get {
96 96 return m_promise;
97 97 }
98 98 }
99 99
100 100 protected override void Worker() {
101 101 TraceContext.Instance.EnterLogicalOperation(m_logicalOperation,false);
102 102 try {
103 103 base.Worker();
104 104 } finally {
105 105 TraceContext.Instance.Leave();
106 106 }
107 107 }
108 108
109 109 protected override bool TryDequeue(out int unit) {
110 110 unit = Interlocked.Increment(ref m_next) - 1;
111 111 return unit < m_source.Length;
112 112 }
113 113
114 114 protected override void InvokeUnit(int unit) {
115 115 try {
116 116 m_dest[unit] = m_transform(m_source[unit]);
117 117 var pending = Interlocked.Decrement(ref m_pending);
118 118 if (pending == 0)
119 119 m_promise.Resolve(m_dest);
120 120 } catch (Exception e) {
121 121 m_promise.Reject(e);
122 122 }
123 123 }
124 124 }
125 125
126 126 public static IPromise<TDst[]> ParallelMap<TSrc, TDst> (this TSrc[] source, Func<TSrc,TDst> transform, int threads) {
127 127 if (source == null)
128 128 throw new ArgumentNullException("source");
129 129 if (transform == null)
130 130 throw new ArgumentNullException("transform");
131 131
132 132 var mapper = new ArrayMapper<TSrc, TDst>(source, transform, threads);
133 133 return mapper.Promise;
134 134 }
135 135
136 136 public static IPromise<int> ParallelForEach<TSrc>(this TSrc[] source, Action<TSrc> action, int threads) {
137 137 if (source == null)
138 138 throw new ArgumentNullException("source");
139 139 if (action == null)
140 140 throw new ArgumentNullException("action");
141 141
142 142 var iter = new ArrayIterator<TSrc>(source, action, threads);
143 143 return iter.Promise;
144 144 }
145 145
146 146 public static IPromise<TDst[]> ChainedMap<TSrc, TDst>(this TSrc[] source, Func<TSrc, IPromise<TDst>> transform, int threads) {
147 147 if (source == null)
148 148 throw new ArgumentNullException("source");
149 149 if (transform == null)
150 150 throw new ArgumentNullException("transform");
151 151 if (threads <= 0)
152 152 throw new ArgumentOutOfRangeException("threads","Threads number must be greater then zero");
153 153
154 154 if (source.Length == 0)
155 155 return Promise<TDst[]>.ResultToPromise(new TDst[0]);
156 156
157 157 var promise = new Promise<TDst[]>();
158 158 var res = new TDst[source.Length];
159 159 var pending = source.Length;
160 160
161 161 object locker = new object();
162 162 int slots = threads;
163 163
164 164 // Analysis disable AccessToDisposedClosure
165 165 AsyncPool.InvokeNewThread(() => {
166 166 for (int i = 0; i < source.Length; i++) {
167 167 if(promise.IsResolved)
168 168 break; // stop processing in case of error or cancellation
169 169 var idx = i;
170 170
171 171 if (Interlocked.Decrement(ref slots) < 0) {
172 172 lock(locker) {
173 173 while(slots < 0)
174 174 Monitor.Wait(locker);
175 175 }
176 176 }
177 177
178 178 try {
179 179 transform(source[i])
180 180 .Anyway(() => {
181 181 Interlocked.Increment(ref slots);
182 182 lock (locker) {
183 183 Monitor.Pulse(locker);
184 184 }
185 185 })
186 .Last(
186 .On(
187 187 x => {
188 188 res[idx] = x;
189 189 var left = Interlocked.Decrement(ref pending);
190 190 if (left == 0)
191 191 promise.Resolve(res);
192 192 },
193 193 promise.Reject
194 194 );
195 195
196 196 } catch (Exception e) {
197 197 promise.Reject(e);
198 198 }
199 199 }
200 200 return 0;
201 201 });
202 202
203 203 return promise;
204 204 }
205 205
206 206 }
207 207 }
@@ -1,908 +1,932
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.Reflection;
4 4 using System.Threading;
5 5 using Implab.Parallels;
6 6
7 7 namespace Implab {
8 8
9 9 /// <summary>
10 10 /// Класс для асинхронного получСния Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ². Π’Π°ΠΊ Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΠΎΠ΅ "ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅".
11 11 /// </summary>
12 12 /// <typeparam name="T">Π’ΠΈΠΏ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌΠΎΠ³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°</typeparam>
13 13 /// <remarks>
14 14 /// <para>БСрвис ΠΏΡ€ΠΈ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ ΠΊ Π΅Π³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρƒ Π΄Π°Π΅Ρ‚ ΠΎΠ±Π΅Ρ‰Π°ΠΈΠ½ΠΈΠ΅ ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ,
15 15 /// ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ² Ρ‚Π°ΠΊΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ряд ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹Ρ… Π²Ρ‹Π·ΠΎΠ²ΠΎ для получСния
16 16 /// событий выполнСния обСщания, Ρ‚ΠΎΠ΅ΡΡ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΈ прСдоставлСнии Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ².</para>
17 17 /// <para>
18 18 /// ΠžΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚Π°ΠΊ ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ с ошибкой. Для подписки Π½Π°
19 19 /// Π΄Π°Π½Π½Ρ‹Π΅ события ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Then</c>.
20 20 /// </para>
21 21 /// <para>
22 22 /// БСрвис, Π² свою ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ, ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ (Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ с ошибкой),
23 23 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Resolve</c> Π»ΠΈΠ±ΠΎ <c>Reject</c> для оповСщСния ΠΊΠ»ΠΈΠ΅Ρ‚Π½Π° ΠΎ
24 24 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ обСщания.
25 25 /// </para>
26 26 /// <para>
27 27 /// Если сСрвСр успСл Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΅Ρ‰Π΅ Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π½Π° Π½Π΅Π³ΠΎ подписался,
28 28 /// Ρ‚ΠΎ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ подписки ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΠ²ΡƒΡŽΡ‰ΠΈΠ΅ события Π² синхронном
29 29 /// Ρ€Π΅ΠΆΠΈΠΌΠ΅ ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΠΎΠ²Π΅Ρ‰Π΅Π½ Π² любом случаС. Π˜Π½Π°Ρ‡Π΅, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ΡΡ Π²
30 30 /// список Π² порядкС подписания ΠΈ Π² этом ΠΆΠ΅ порядкС ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ
31 31 /// обСщания.
32 32 /// </para>
33 33 /// <para>
34 34 /// ΠžΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ обСщания ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Π»ΠΈΠ±ΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ
35 35 /// связанныС асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ‚Π°ΠΊΠΆΠ΅ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ обСщания. Для этого слСдуСт
36 36 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ Ρ„ΠΎΡ€ΠΌΡƒ ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ <c>Then</c>.
37 37 /// </para>
38 38 /// <para>
39 39 /// Π’Π°ΠΊΠΆΠ΅ Ρ…ΠΎΡ€ΠΎΡˆΠΈΠΌ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎΠΌ являСтся Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ <c>Resolve</c> ΠΈ <c>Reject</c> Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ
40 40 /// Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€ обСщания ΠΈΠ½Π°Ρ‡Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ΡŒ противорСчия.
41 41 /// </para>
42 42 /// </remarks>
43 43 public class Promise<T> : IPromise<T> {
44 44
45 45 protected struct HandlerDescriptor {
46 46 public Action<T> resultHandler;
47 47 public Func<Exception,T> errorHandler;
48 48 public Action cancellHandler;
49 49 public Promise<T> medium;
50 50
51 51 public void Resolve(T result) {
52 52 if (resultHandler != null) {
53 53 try {
54 54 resultHandler(result);
55 55 } catch (Exception e) {
56 56 Reject(e);
57 57 return;
58 58 }
59 59 }
60 60 if (medium != null)
61 61 medium.Resolve(result);
62 62 }
63 63
64 64 public void Reject(Exception err) {
65 65 if (errorHandler != null) {
66 66 try {
67 67 var res = errorHandler(err);
68 68 if (medium != null)
69 69 medium.Resolve(res);
70 70 /*} catch (TransientPromiseException err2) {
71 71 if (medium != null)
72 72 medium.Reject(err2.InnerException);*/
73 73 } catch (Exception err2) {
74 74 if (medium != null)
75 75 medium.Reject(err2);
76 76 }
77 77 } else if (medium != null)
78 78 medium.Reject(err);
79 79 }
80 80
81 81 public void Cancel() {
82 82 if (cancellHandler != null) {
83 83 try {
84 84 cancellHandler();
85 85 } catch (Exception err) {
86 86 Reject(err);
87 87 return;
88 88 }
89 89 }
90 90 if (medium != null)
91 91 medium.Cancel();
92 92 }
93 93 }
94 94
95 95 const int UNRESOLVED_SATE = 0;
96 96 const int TRANSITIONAL_STATE = 1;
97 97 const int SUCCEEDED_STATE = 2;
98 98 const int REJECTED_STATE = 3;
99 99 const int CANCELLED_STATE = 4;
100 100
101 101 int m_childrenCount;
102 102 int m_state;
103 103 T m_result;
104 104 Exception m_error;
105 105
106 106 readonly MTQueue<HandlerDescriptor> m_handlers = new MTQueue<HandlerDescriptor>();
107 107
108 108 public Promise() {
109 109 }
110 110
111 111 public Promise(IPromise parent) {
112 112 if (parent != null)
113 113 AddHandler(
114 114 null,
115 115 null,
116 116 () => {
117 117 if (parent.IsExclusive)
118 118 parent.Cancel();
119 119 },
120 null
120 null,
121 false
121 122 );
122 123 }
123 124
124 125 bool BeginTransit() {
125 126 return UNRESOLVED_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, UNRESOLVED_SATE);
126 127 }
127 128
128 129 void CompleteTransit(int state) {
129 130 if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, state, TRANSITIONAL_STATE))
130 131 throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state");
131 132 }
132 133
133 134 void WaitTransition() {
134 135 while (m_state == TRANSITIONAL_STATE) {
135 136 Thread.MemoryBarrier();
136 137 }
137 138 }
138 139
139 140 public bool IsResolved {
140 141 get {
141 142 Thread.MemoryBarrier();
142 143 return m_state > 1;
143 144 }
144 145 }
145 146
146 147 public bool IsCancelled {
147 148 get {
148 149 Thread.MemoryBarrier();
149 150 return m_state == CANCELLED_STATE;
150 151 }
151 152 }
152 153
153 154 public Type PromiseType {
154 155 get { return typeof(T); }
155 156 }
156 157
157 158 /// <summary>
158 159 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ.
159 160 /// </summary>
160 161 /// <param name="result">Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния.</param>
161 162 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
162 163 public void Resolve(T result) {
163 164 if (BeginTransit()) {
164 165 m_result = result;
165 166 CompleteTransit(SUCCEEDED_STATE);
166 167 OnStateChanged();
167 168 } else {
168 169 WaitTransition();
169 170 if (m_state != CANCELLED_STATE)
170 171 throw new InvalidOperationException("The promise is already resolved");
171 172 }
172 173 }
173 174
174 175 /// <summary>
175 176 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ. Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ выполнСния Π±ΡƒΠ΄Π΅Ρ‚ пустоС значСния.
176 177 /// </summary>
177 178 /// <remarks>
178 179 /// Π”Π°Π½Π½Ρ‹ΠΉ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ ΡƒΠ΄ΠΎΠ±Π΅Π½ Π² случаях, ΠΊΠΎΠ³Π΄Π° интСрСсСн Ρ„Π°ΠΊΡ‚ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, Π½Π΅ΠΆΠ΅Π»ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.
179 180 /// </remarks>
180 181 public void Resolve() {
181 182 Resolve(default(T));
182 183 }
183 184
184 185 /// <summary>
185 186 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ошибкС
186 187 /// </summary>
187 188 /// <remarks>
188 189 /// ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС, ΠΏΡ€ΠΈ Π΅Π³ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ сразу нСсколько ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²
189 190 /// ΠΌΠΎΠ³Ρƒ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ, ΠΏΡ€ΠΈ этом Ρ‚ΠΎΠ»ΡŒΠΊΠΎ пСрвая Π±ΡƒΠ΄Π΅Ρ‚ использована Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅
190 191 /// Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΡ€ΠΎΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹.
191 192 /// </remarks>
192 193 /// <param name="error">Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ</param>
193 194 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
194 195 public void Reject(Exception error) {
195 196 if (BeginTransit()) {
196 197 m_error = error is TransientPromiseException ? error.InnerException : error;
197 198 CompleteTransit(REJECTED_STATE);
198 199 OnStateChanged();
199 200 } else {
200 201 WaitTransition();
201 202 if (m_state == SUCCEEDED_STATE)
202 203 throw new InvalidOperationException("The promise is already resolved");
203 204 }
204 205 }
205 206
206 207 /// <summary>
207 208 /// ΠžΡ‚ΠΌΠ΅Π½ΡΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.
208 209 /// </summary>
209 210 /// <remarks>Для опрСдСлСния Π±Ρ‹Π»Π° Π»ΠΈ опСрация ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Π° слСдуСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ свойство <see cref="IsCancelled"/>.</remarks>
210 211 public void Cancel() {
211 212 if (BeginTransit()) {
212 213 CompleteTransit(CANCELLED_STATE);
213 214 OnStateChanged();
214 215 }
215 216 }
216 217
217 218 public IPromise<T> Then(Action<T> success, Func<Exception,T> error, Action cancel) {
218 219 if (success == null && error == null && cancel == null)
219 220 return this;
220 221
221 222 var medium = new Promise<T>(this);
222 223
223 AddHandler(success, error, cancel, medium);
224 AddHandler(success, error, cancel, medium, true);
224 225
225 226 return medium;
226 227 }
227 228
228 229 /// <summary>
229 230 /// Adds new handlers to this promise.
230 231 /// </summary>
231 232 /// <param name="success">The handler of the successfully completed operation.
232 233 /// This handler will recieve an operation result as a parameter.</param>
233 234 /// <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>
234 235 /// <returns>The new promise chained to this one.</returns>
235 236 public IPromise<T> Then(Action<T> success, Func<Exception,T> error) {
236 237 if (success == null && error == null)
237 238 return this;
238 239
239 240 var medium = new Promise<T>(this);
240 241
241 AddHandler(success, error, null, medium);
242 AddHandler(success, error, null, medium, true);
242 243
243 244 return medium;
244 245 }
245 246
246 247
247 248
248 249
249 250 public IPromise<T> Then(Action<T> success) {
250 251 if (success == null)
251 252 return this;
252 253
253 254 var medium = new Promise<T>(this);
254 255
255 AddHandler(success, null, null, medium);
256 AddHandler(success, null, null, medium, true);
256 257
257 258 return medium;
258 259 }
259 260
260 261 /// <summary>
261 262 /// ПослСдний ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
262 263 /// </summary>
263 264 /// <param name="success"></param>
264 265 /// <param name="error"></param>
265 266 /// <param name="cancel"></param>
266 267 /// <remarks>
267 268 /// <para>
268 269 /// Π”Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π½Π΅ создаСт связанного с Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΌ обСщания ΠΈ ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½ для окончания
269 270 /// фсинхронной Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ.
270 271 /// </para>
271 272 /// <para>
272 273 /// Если Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ нСсколько Ρ€Π°Π·, Π»ΠΈΠ±ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, Ρ‚ΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ°
273 274 /// Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ΄ΠΈΠ½ΠΎΡ‡Π½ΠΎΠΉ <see cref="IsExclusive"/> ΠΈ, ΠΊΠ°ΠΊ слСдствиС, Π±ΡƒΠ΄Π΅Ρ‚ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π° ΠΎΡ‚ΠΌΠ΅Π½Π°
274 275 /// всСй Ρ†Π΅ΠΏΠΈ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ снизу (с самого послСднСго обСщания).
275 276 /// </para>
276 277 /// </remarks>
277 public void Last(Action<T> success, Action<Exception> error, Action cancel) {
278 public void On(Action<T> success, Action<Exception> error, Action cancel) {
278 279 if (success == null && error == null && cancel == null)
279 280 return;
280 281
281 282 Func<Exception,T> errorHandler = null;
282 283 if (error != null)
283 284 errorHandler = err => {
284 285 error(err);
285 286 return default(T);
286 287 };
287 AddHandler(success, errorHandler, cancel, null);
288 AddHandler(success, errorHandler, cancel, null, false);
289 }
290
291 public void On(Action<T> success, Action<Exception> error) {
292 On(success, error, null);
293 }
294
295 public void On(Action<T> success) {
296 On(success, null, null);
288 297 }
289 298
290 public void Last(Action<T> success, Action<Exception> error) {
291 Last(success, error, null);
292 }
299 public void On(Action handler, PromiseEventType events) {
300 Safe.ArgumentNotNull(handler, "handler");
293 301
294 public void Last(Action<T> success) {
295 Last(success, null, null);
302 Action<T> success = events.HasFlag(PromiseEventType.Success) ? new Action<T>(x => handler()) : null;
303 Func<Exception,T> error = events.HasFlag(PromiseEventType.Error) ? new Func<Exception,T>(e => {
304 handler();
305 return default(T);
306 }) : null;
307 Action cancel = events.HasFlag(PromiseEventType.Cancelled) ? handler : null;
308
309 AddHandler(success, error, cancel, null, false);
296 310 }
297 311
298 312 public IPromise Error(Action<Exception> error) {
299 313 if (error == null)
300 314 return this;
301 315
302 316 var medium = new Promise<T>(this);
303 317
304 318 AddHandler(
305 319 null,
306 320 e => {
307 321 error(e);
308 322 return default(T);
309 323 },
310 324 null,
311 medium
325 medium,
326 true
312 327 );
313 328
314 329 return medium;
315 330 }
316 331
317 332 /// <summary>
318 333 /// Handles error and allows to keep the promise.
319 334 /// </summary>
320 335 /// <remarks>
321 336 /// If the specified handler throws an exception, this exception will be used to reject the promise.
322 337 /// </remarks>
323 338 /// <param name="handler">The error handler which returns the result of the promise.</param>
324 339 /// <returns>New promise.</returns>
325 340 public IPromise<T> Error(Func<Exception,T> handler) {
326 341 if (handler == null)
327 342 return this;
328 343
329 344 var medium = new Promise<T>(this);
330 345
331 AddHandler(null, handler, null, medium);
346 AddHandler(null, handler, null, medium, true);
332 347
333 348 return medium;
334 349 }
335 350
336 351 /// <summary>
337 352 /// ΠŸΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ‚ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.
338 353 /// </summary>
339 354 /// <typeparam name="TNew">Новый Ρ‚ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°.</typeparam>
340 355 /// <param name="mapper">ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.</param>
341 356 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
342 357 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
343 358 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ исходного обСщания.</returns>
344 359 /// <param name = "cancel"></param>
345 360 public IPromise<TNew> Then<TNew>(Func<T, TNew> mapper, Func<Exception,TNew> error, Action cancel) {
346 361 Safe.ArgumentNotNull(mapper, "mapper");
347 362
348 363 // создаСм ΠΏΡ€ΠΈΡ†Π΅ΠΏΠ»Π΅Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
349 364 var medium = new Promise<TNew>(this);
350 365
351 366 Action<T> resultHandler = result => medium.Resolve(mapper(result));
352 367 Func<Exception,T> errorHandler;
353 368 if (error != null)
354 369 errorHandler = e => {
355 370 try {
356 371 medium.Resolve(error(e));
357 372 } catch (Exception e2) {
358 373 // Π² случаС ошибки Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅
359 374 medium.Reject(e2);
360 375 }
361 376 return default(T);
362 377 };
363 378 else
364 379 errorHandler = e => {
365 380 medium.Reject(e);
366 381 return default(T);
367 382 };
368 383
369 384 Action cancelHandler;
370 385 if (cancel != null)
371 386 cancelHandler = () => {
372 387 cancel();
373 388 medium.Cancel();
374 389 };
375 390 else
376 391 cancelHandler = medium.Cancel;
377 392
378 393
379 394 AddHandler(
380 395 resultHandler,
381 396 errorHandler,
382 397 cancelHandler,
383 null
398 null,
399 true
384 400 );
385 401
386 402 return medium;
387 403 }
388 404
389 405 public IPromise<TNew> Then<TNew>(Func<T, TNew> mapper, Func<Exception,TNew> error) {
390 406 return Then(mapper, error, null);
391 407 }
392 408
393 409 public IPromise<TNew> Then<TNew>(Func<T, TNew> mapper) {
394 410 return Then(mapper, null, null);
395 411 }
396 412
397 413 /// <summary>
398 414 /// БцСпляСт нСсколько аснхронных ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ. Указанная асинхронная опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½Π° послС
399 415 /// выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ, Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ использован для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ
400 416 /// Π½ΠΎΠ²ΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.
401 417 /// </summary>
402 418 /// <typeparam name="TNew">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</typeparam>
403 419 /// <param name="chained">Асинхронная опСрация, которая Π΄ΠΎΠ»ΠΆΠ½Π° Π±ΡƒΠ΄Π΅Ρ‚ Π½Π°Ρ‡Π°Ρ‚ΡŒΡΡ послС выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ.</param>
404 420 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
405 421 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Ρ‚Π΅ΠΊΡƒΠ΅Ρ‰ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
406 422 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ аснхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</returns>
407 423 /// <param name = "cancel"></param>
408 424 public IPromise<TNew> Chain<TNew>(Func<T, IPromise<TNew>> chained, Func<Exception,IPromise<TNew>> error, Action cancel) {
409 425
410 426 Safe.ArgumentNotNull(chained, "chained");
411 427
412 428 // ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ‚ связывания Π΅Ρ‰Π΅ Π½Π΅ Π½Π°Ρ‡Π°Ρ‚Π° асинхронная опСрация, поэтому Π½ΡƒΠΆΠ½ΠΎ
413 429 // ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ посрСдника, ΠΊ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠΎΠ΄Π²Ρ‹Π·ΡΠ²Π°Ρ‚ΡŒΡΡ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ.
414 430 // ΠΊΠΎΠ³Π΄Π° Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° Ρ€Π΅Π°Π»ΡŒΠ½Π°Ρ асинхронная опСрация, ΠΎΠ½Π° ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ ΠΊ посрСднику, Ρ‡Ρ‚ΠΎΠ±Ρ‹
415 431 // ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· Π½Π΅Π³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Ρ€Π°Π±ΠΎΡ‚Ρ‹.
416 432 var medium = new Promise<TNew>(this);
417 433
418 434 Action<T> resultHandler = delegate(T result) {
419 435 if (medium.IsCancelled)
420 436 return;
421 437
422 438 var promise = chained(result);
423 439
424 promise.Last(
440 promise.On(
425 441 medium.Resolve,
426 442 medium.Reject,
427 443 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
428 444 );
429 445
430 446 // notify chained operation that it's not needed anymore
431 447 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
432 448 // зависит IsExclusive
433 medium.Last(
449 medium.On(
434 450 null,
435 451 null,
436 452 () => {
437 453 if (promise.IsExclusive)
438 454 promise.Cancel();
439 455 }
440 456 );
441 457 };
442 458
443 459 Func<Exception,T> errorHandler;
444 460
445 461 if (error != null)
446 462 errorHandler = delegate(Exception e) {
447 463 try {
448 464 var promise = error(e);
449 465
450 promise.Last(
466 promise.On(
451 467 medium.Resolve,
452 468 medium.Reject,
453 469 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
454 470 );
455 471
456 472 // notify chained operation that it's not needed anymore
457 473 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
458 474 // зависит IsExclusive
459 475 medium.Cancelled(() => {
460 476 if (promise.IsExclusive)
461 477 promise.Cancel();
462 478 });
463 479 } catch (Exception e2) {
464 480 medium.Reject(e2);
465 481 }
466 482 return default(T);
467 483 };
468 484 else
469 485 errorHandler = err => {
470 486 medium.Reject(err);
471 487 return default(T);
472 488 };
473 489
474 490
475 491 Action cancelHandler;
476 492 if (cancel != null)
477 493 cancelHandler = () => {
478 494 if (cancel != null)
479 495 cancel();
480 496 medium.Cancel();
481 497 };
482 498 else
483 499 cancelHandler = medium.Cancel;
484 500
485 501 AddHandler(
486 502 resultHandler,
487 503 errorHandler,
488 504 cancelHandler,
489 null
505 null,
506 true
490 507 );
491 508
492 509 return medium;
493 510 }
494 511
495 512 public IPromise<TNew> Chain<TNew>(Func<T, IPromise<TNew>> chained, Func<Exception,IPromise<TNew>> error) {
496 513 return Chain(chained, error, null);
497 514 }
498 515
499 516 public IPromise<TNew> Chain<TNew>(Func<T, IPromise<TNew>> chained) {
500 517 return Chain(chained, null, null);
501 518 }
502 519
503 520 public IPromise<T> Cancelled(Action handler) {
504 521 var medium = new Promise<T>(this);
505 AddHandler(null, null, handler, medium);
522 AddHandler(null, null, handler, medium, false);
506 523 return medium;
507 524 }
508 525
509 526 /// <summary>
510 527 /// Adds the specified handler for all cases (success, error, cancel)
511 528 /// </summary>
512 529 /// <param name="handler">The handler that will be called anyway</param>
513 530 /// <returns>self</returns>
514 531 public IPromise<T> Anyway(Action handler) {
515 532 Safe.ArgumentNotNull(handler, "handler");
516
533
534 var medium = new Promise<T>(this);
535
517 536 AddHandler(
518 537 x => handler(),
519 538 e => {
520 539 handler();
521 540 throw new TransientPromiseException(e);
522 541 },
523 542 handler,
524 null
543 medium,
544 true
525 545 );
526 return this;
546
547 return medium;
527 548 }
528 549
529 550 /// <summary>
530 551 /// ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ обСщания ΠΊ Π½ΡƒΠΆΠ½ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ
531 552 /// </summary>
532 553 /// <typeparam name="T2"></typeparam>
533 554 /// <returns></returns>
534 555 public IPromise<T2> Cast<T2>() {
535 556 return Then(x => (T2)(object)x, null);
536 557 }
537 558
538 559 /// <summary>
539 560 /// ДоТидаСтся ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ³ΠΎ обСщания ΠΈ Π² случаС успСха, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚
540 561 /// Π΅Π³ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС бросаСт ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.
541 562 /// </summary>
542 563 /// <remarks>
543 564 /// <para>
544 565 /// Если ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ обСщания Π±Ρ‹Π»ΠΎ ΠΏΡ€Π΅Ρ€Π²Π°Π½ΠΎ ΠΏΠΎ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚Ρƒ, это Π½Π΅ Π·Π½Π°Ρ‡ΠΈΡ‚,
545 566 /// Ρ‡Ρ‚ΠΎ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±Ρ‹Π»ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½ΠΎ ΠΈΠ»ΠΈ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π² этом Ρ€ΠΎΠ΄Π΅, это Ρ‚ΠΎΠ»ΡŒΠΊΠΎ
546 567 /// ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π΅Π³ΠΎ Π½Π΅ доТдались, ΠΎΠ΄Π½Π°ΠΊΠΎ всС зарСгистрированныС
547 568 /// ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, ΠΊΠ°ΠΊ Π±Ρ‹Π»ΠΈ Ρ‚Π°ΠΊ ΠΎΡΡ‚Π°Π»ΠΈΡΡŒ ΠΈ ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹, ΠΊΠΎΠ³Π΄Π°
548 569 /// ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
549 570 /// </para>
550 571 /// <para>
551 572 /// Π’Π°ΠΊΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π²ΠΏΠΎΠ»Π½Π΅ ΠΎΠΏΡ€Π°Π²Π΄Π°Π½ΠΎ ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΡ‚Π΅Ρ‡ΡŒ
552 573 /// Π² Ρ‚ΠΎΡ‚ ΠΌΠΎΠΌΠ΅Π½Ρ‚, ΠΊΠΎΠ³Π΄Π° Π½Π°Ρ‡Π°Π»Π°ΡΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ², ΠΈ
553 574 /// ΠΊ Ρ‚ΠΎΠΌΡƒ ΠΆΠ΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡ‚ΠΎΡΡ‚ΡŒ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ ΠΈ Π΅Π³ΠΎ
554 575 /// ΠΎΡ‚ΠΊΠ»ΠΎΠ½Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ Π½Π΅ΠΏΡ€ΠΎΠ³Π½ΠΎΠ·ΠΈΡ€ΡƒΠ΅ΠΌΠΎΠΌΡƒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρƒ.
555 576 /// </para>
556 577 /// </remarks>
557 578 /// <param name="timeout">ВрСмя оТидания</param>
558 579 /// <returns>Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния обСщания</returns>
559 580 public T Join(int timeout) {
560 581 var evt = new ManualResetEvent(false);
561 582 Anyway(() => evt.Set());
562 583
563 584 if (!evt.WaitOne(timeout, true))
564 585 throw new TimeoutException();
565 586
566 587 switch (m_state) {
567 588 case SUCCEEDED_STATE:
568 589 return m_result;
569 590 case CANCELLED_STATE:
570 591 throw new OperationCanceledException();
571 592 case REJECTED_STATE:
572 593 throw new TargetInvocationException(m_error);
573 594 default:
574 595 throw new ApplicationException(String.Format("Invalid promise state {0}", m_state));
575 596 }
576 597 }
577 598
578 599 public T Join() {
579 600 return Join(Timeout.Infinite);
580 601 }
581 602
582 void AddHandler(Action<T> success, Func<Exception,T> error, Action cancel, Promise<T> medium) {
583 if (success != null || error != null)
603 void AddHandler(Action<T> success, Func<Exception,T> error, Action cancel, Promise<T> medium, bool inc) {
604 if (inc)
584 605 Interlocked.Increment(ref m_childrenCount);
585 606
586 607 var handler = new HandlerDescriptor {
587 608 resultHandler = success,
588 609 errorHandler = error,
589 610 cancellHandler = cancel,
590 611 medium = medium
591 612 };
592 613
593 614 bool queued;
594 615
595 616 if (!IsResolved) {
596 617 m_handlers.Enqueue(handler);
597 618 queued = true;
598 619 } else {
599 620 // the promise is in resolved state, just invoke the handled with minimum overhead
600 621 queued = false;
601 622 InvokeHandler(handler);
602 623 }
603 624
604 625 if (queued && IsResolved && m_handlers.TryDequeue(out handler))
605 626 // if the promise have been resolved while we was adding handler to the queue
606 627 // we can't guarantee that someone is still processing it
607 628 // therefore we will fetch a handler from the queue and execute it
608 629 // note that fetched handler may be not the one that we have added
609 630 // even we can fetch no handlers at all :)
610 631 InvokeHandler(handler);
611 632 }
612 633
613 634 protected virtual void InvokeHandler(HandlerDescriptor handler) {
614 635 switch (m_state) {
615 636 case SUCCEEDED_STATE:
616 637 handler.Resolve(m_result);
617 638 break;
618 639 case REJECTED_STATE:
619 640 handler.Reject(m_error);
620 641 break;
621 642 case CANCELLED_STATE:
622 643 handler.Cancel();
623 644 break;
624 645 default:
625 646 // do nothing
626 647 return;
627 648 }
628 649 }
629 650
630 651 void OnStateChanged() {
631 652 HandlerDescriptor handler;
632 653 while (m_handlers.TryDequeue(out handler))
633 654 InvokeHandler(handler);
634 655 }
635 656
636 657 public bool IsExclusive {
637 658 get {
638 659 return m_childrenCount <= 1;
639 660 }
640 661 }
641 662
642 663 /// <summary>
643 664 /// ΠžΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ нСсколько ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ являСтся массив Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
644 665 /// Если хотябы ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚ΠΎ Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ Ρ‚ΠΎΠΆΠ΅ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
645 666 /// ΠŸΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ Π½ΠΎΠ²ΠΎΠ³ΠΎ обСщания, ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅ обСщания Ρ‚Π°ΠΊΠΆΠ΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Ρ‹, Ссли Π½ΠΈΠΊΡ‚ΠΎ большС Π½Π° Π½ΠΈΡ… Π½Π΅ подписан.
646 667 /// </summary>
647 668 /// <param name="promises">Бписок ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ. Если список пустой, Ρ‚ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ возвращаСтся ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹ΠΌ.</param>
648 669 /// <returns>ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰Π΅Π΅ Π² сСбС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.</returns>
649 670 /// <exception cref="ArgumentNullException"><paramref name="promises"/> Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ null</exception>
650 671 public static IPromise<T[]> CreateComposite(IList<IPromise<T>> promises) {
651 672 if (promises == null)
652 673 throw new ArgumentNullException();
653 674
654 675 // создаСм аккумулятор для Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² ΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
655 676 var result = new T[promises.Count];
656 677 var promise = new Promise<T[]>();
657 678
658 679 // special case
659 680 if (promises.Count == 0) {
660 681 promise.Resolve(result);
661 682 return promise;
662 683 }
663 684
664 685 int pending = promises.Count;
665 686
666 687 for (int i = 0; i < promises.Count; i++) {
667 688 var dest = i;
668 689
669 690 if (promises[i] != null) {
670 691 promises[i].Then(
671 692 x => {
672 693 result[dest] = x;
673 694 if (Interlocked.Decrement(ref pending) == 0)
674 695 promise.Resolve(result);
675 696 },
676 697 e => {
677 698 promise.Reject(e);
678 699 return default(T);
679 700 }
680 701 );
681 702 } else {
682 703 if (Interlocked.Decrement(ref pending) == 0)
683 704 promise.Resolve(result);
684 705 }
685 706 }
686 707
687 708 promise.Cancelled(
688 709 () => {
689 710 foreach (var d in promises)
690 711 if (d != null && d.IsExclusive)
691 712 d.Cancel();
692 713 }
693 714 );
694 715
695 716 return promise;
696 717 }
697 718
698 719 /// <summary>
699 720 /// ΠžΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ нСсколько ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ. Π Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ
700 721 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ всСх ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ. ΠŸΡ€ΠΈ этом Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹Π΅ значСния ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ
701 722 /// ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΡƒΡŽΡ‚ΡΡ.
702 723 /// </summary>
703 724 /// <param name="promises">ΠšΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΡ ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΠ±ΡŠΠ΅Π΄Π΅Π½Π΅Π½Ρ‹ Π² ΠΎΠ΄Π½ΠΎ.</param>
704 725 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰Π΅Π΅ Π² сСбС ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅.</returns>
705 726 /// <remarks>
706 727 /// Если Π² ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΈ Π²ΡΡ‚Ρ€Π΅Ρ‡Π°ΡŽΡŒΡΡ <c>null</c>, Ρ‚ΠΎ ΠΎΠ½ΠΈ Π²ΠΎΡΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹Π΅ обСщания.
707 728 /// </remarks>
708 729 public static IPromise CreateComposite(ICollection<IPromise> promises) {
709 730 if (promises == null)
710 731 throw new ArgumentNullException();
711 732 if (promises.Count == 0)
712 733 return Promise<object>.ResultToPromise(null);
713 734
714 735 int countdown = promises.Count;
715 736
716 737 var result = new Promise<object>();
717 738
718 739 foreach (var d in promises) {
719 740 if (d == null) {
720 741 if (Interlocked.Decrement(ref countdown) == 0)
721 742 result.Resolve(null);
722 743 } else {
723 744 d.Then(() => {
724 745 if (Interlocked.Decrement(ref countdown) == 0)
725 746 result.Resolve(null);
726 747 });
727 748 }
728 749 }
729 750
730 751 result.Cancelled(() => {
731 752 foreach (var d in promises)
732 753 if (d != null && d.IsExclusive)
733 754 d.Cancel();
734 755 });
735 756
736 757 return result;
737 758 }
738 759
739 760 public static Promise<T> ResultToPromise(T result) {
740 761 var p = new Promise<T>();
741 762 p.Resolve(result);
742 763 return p;
743 764 }
744 765
745 766 public static Promise<T> ExceptionToPromise(Exception error) {
746 767 if (error == null)
747 768 throw new ArgumentNullException();
748 769
749 770 var p = new Promise<T>();
750 771 p.Reject(error);
751 772 return p;
752 773 }
753 774
754 775 #region IPromiseBase explicit implementation
755 776
756 777 IPromise IPromise.Then(Action success, Action<Exception> error, Action cancel) {
757 778 return Then(
758 779 success != null ? new Action<T>(x => success()) : null,
759 780 error != null ? new Func<Exception,T>(e => {
760 781 error(e);
761 782 return default(T);
762 783 }) : null,
763 784 cancel
764 785 );
765 786 }
766 787
767 788 IPromise IPromise.Then(Action success, Action<Exception> error) {
768 789 return Then(
769 790 success != null ? new Action<T>(x => success()) : null,
770 791 error != null ? new Func<Exception,T>(e => {
771 792 error(e);
772 793 return default(T);
773 794 }) : null
774 795 );
775 796 }
776 797
777 798 IPromise IPromise.Then(Action success) {
778 799 Safe.ArgumentNotNull(success, "success");
779 800 return Then(x => success());
780 801 }
781 802
782 803 IPromise IPromise.Chain(Func<IPromise> chained, Func<Exception,IPromise> error, Action cancel) {
783 804 return ChainNoResult(chained, error, cancel);
784 805 }
785 806
786 807 IPromise ChainNoResult(Func<IPromise> chained, Func<Exception,IPromise> error, Action cancel) {
787 Safe.ArgumentNotNull(chained, "chained");
808 Safe.ArgumentNotNull(chained, "chained");
788 809
789 810 var medium = new Promise<object>(this);
790 811
791 812 Action<T> resultHandler = delegate {
792 if (medium.IsCancelled)
793 return;
813 if (medium.IsCancelled)
814 return;
794 815
795 var promise = chained();
816 var promise = chained();
796 817
797 promise.Last(
798 medium.Resolve,
799 medium.Reject,
800 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
801 );
818 promise.On(
819 medium.Resolve,
820 medium.Reject,
821 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
822 );
802 823
803 // notify chained operation that it's not needed anymore
804 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
805 // зависит IsExclusive
806 medium.Cancelled(() => {
807 if (promise.IsExclusive)
808 promise.Cancel();
809 });
810 };
824 // notify chained operation that it's not needed anymore
825 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
826 // зависит IsExclusive
827 medium.Cancelled(() => {
828 if (promise.IsExclusive)
829 promise.Cancel();
830 });
831 };
811 832
812 833 Func<Exception,T> errorHandler;
813 834
814 if (error != null)
815 errorHandler = delegate(Exception e) {
835 if (error != null)
836 errorHandler = delegate(Exception e) {
816 837 try {
817 838 var promise = error(e);
818 839
819 promise.Last(
840 promise.On(
820 841 medium.Resolve,
821 842 medium.Reject,
822 843 () => medium.Reject(new OperationCanceledException()) // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
823 844 );
824 845
825 846 // notify chained operation that it's not needed anymore
826 847 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
827 848 // зависит IsExclusive
828 849 medium.Cancelled(() => {
829 850 if (promise.IsExclusive)
830 851 promise.Cancel();
831 852 });
832 853 } catch (Exception e2) {
833 854 medium.Reject(e2);
834 855 }
835 856 return default(T);
836 857 };
837 else
838 errorHandler = err => {
858 else
859 errorHandler = err => {
839 860 medium.Reject(err);
840 861 return default(T);
841 862 };
842 863
843 864
844 Action cancelHandler;
845 if (cancel != null)
846 cancelHandler = () => {
865 Action cancelHandler;
866 if (cancel != null)
867 cancelHandler = () => {
847 868 if (cancel != null)
848 869 cancel();
849 870 medium.Cancel();
850 871 };
851 else
852 cancelHandler = medium.Cancel;
872 else
873 cancelHandler = medium.Cancel;
853 874
854 AddHandler(
855 resultHandler,
856 errorHandler,
857 cancelHandler,
858 null
859 );
875 AddHandler(
876 resultHandler,
877 errorHandler,
878 cancelHandler,
879 null,
880 true
881 );
860 882
861 return medium;
883 return medium;
862 884 }
885
863 886 IPromise IPromise.Chain(Func<IPromise> chained, Func<Exception,IPromise> error) {
864 887 return ChainNoResult(chained, error, null);
865 888 }
889
866 890 IPromise IPromise.Chain(Func<IPromise> chained) {
867 891 return ChainNoResult(chained, null, null);
868 }
892 }
869 893
870 894
871 void IPromise.Last(Action success, Action<Exception> error, Action cancel) {
872 Last(x => success(), error, cancel);
895 void IPromise.On(Action success, Action<Exception> error, Action cancel) {
896 On(x => success(), error, cancel);
873 897 }
874 898
875 void IPromise.Last(Action success, Action<Exception> error) {
876 Last(x => success(), error, null);
899 void IPromise.On(Action success, Action<Exception> error) {
900 On(x => success(), error, null);
877 901 }
878 902
879 void IPromise.Last(Action success) {
880 Last(x => success(), null, null);
903 void IPromise.On(Action success) {
904 On(x => success(), null, null);
881 905 }
882 906
883 907 IPromise IPromise.Error(Action<Exception> error) {
884 908 return Error(error);
885 909 }
886 910
887 911 IPromise IPromise.Anyway(Action handler) {
888 912 return Anyway(handler);
889 913 }
890 914
891 915 IPromise IPromise.Cancelled(Action handler) {
892 916 return Cancelled(handler);
893 917 }
894 918
895 919 void IPromise.Join() {
896 920 Join();
897 921 }
898 922
899 923 void IPromise.Join(int timeout) {
900 924 Join(timeout);
901 925 }
902 926
903 927 #endregion
904 928
905 929
906 930
907 931 }
908 932 }
@@ -1,83 +1,83
1 1 using System.Threading;
2 2 using System;
3 3 #if NET_4_5
4 4 using System.Threading.Tasks;
5 5 #endif
6 6
7 7 namespace Implab {
8 8 public static class PromiseExtensions {
9 9 public static IPromise<T> DispatchToCurrentContext<T>(this IPromise<T> that) {
10 10 Safe.ArgumentNotNull(that, "that");
11 11 var context = SynchronizationContext.Current;
12 12 if (context == null)
13 13 return that;
14 14
15 15 var p = new SyncContextPromise<T>(context, that);
16 16
17 that.Last(
17 that.On(
18 18 p.Resolve,
19 19 p.Reject,
20 20 p.Cancel
21 21 );
22 22 return p;
23 23 }
24 24
25 25 public static IPromise<T> DispatchToContext<T>(this IPromise<T> that, SynchronizationContext context) {
26 26 Safe.ArgumentNotNull(that, "that");
27 27 Safe.ArgumentNotNull(context, "context");
28 28
29 29 var p = new SyncContextPromise<T>(context, that);
30 30
31 that.Last(
31 that.On(
32 32 p.Resolve,
33 33 p.Reject,
34 34 p.Cancel
35 35 );
36 36 return p;
37 37 }
38 38
39 39 /// <summary>
40 40 /// Ensures the dispatched.
41 41 /// </summary>
42 42 /// <returns>The dispatched.</returns>
43 43 /// <param name="that">That.</param>
44 44 /// <param name="head">Head.</param>
45 45 /// <param name="cleanup">Cleanup.</param>
46 46 /// <typeparam name="TPromise">The 1st type parameter.</typeparam>
47 47 /// <typeparam name="T">The 2nd type parameter.</typeparam>
48 48 public static TPromise EnsureDispatched<TPromise,T>(this TPromise that, IPromise<T> head, Action<T> cleanup) where TPromise : IPromise{
49 49 Safe.ArgumentNotNull(that, "that");
50 50 Safe.ArgumentNotNull(head, "head");
51 51
52 that.Last(null,null,() => head.Last(cleanup));
52 that.On(null,null,() => head.On(cleanup));
53 53
54 54 return that;
55 55 }
56 56
57 57 public static AsyncCallback AsyncCallback<T>(this Promise<T> that, Func<IAsyncResult,T> callback) {
58 58 Safe.ArgumentNotNull(that, "that");
59 59 Safe.ArgumentNotNull(callback, "callback");
60 60 return ar => {
61 61 try {
62 62 that.Resolve(callback(ar));
63 63 } catch (Exception err) {
64 64 that.Reject(err);
65 65 }
66 66 };
67 67 }
68 68
69 69 #if NET_4_5
70 70
71 71 public static Task<T> GetTask<T>(this IPromise<T> that) {
72 72 Safe.ArgumentNotNull(that, "that");
73 73 var tcs = new TaskCompletionSource<T>();
74 74
75 that.Last(tcs.SetResult, tcs.SetException, tcs.SetCanceled);
75 that.On(tcs.SetResult, tcs.SetException, tcs.SetCanceled);
76 76
77 77 return tcs.Task;
78 78 }
79 79
80 80 #endif
81 81 }
82 82 }
83 83
@@ -1,48 +1,48
1 1 using System;
2 2 using Implab.Diagnostics;
3 3 using Implab.Parallels;
4 4 using Implab;
5 5 using System.Collections.Generic;
6 6 using System.Collections.Concurrent;
7 7
8 8 namespace MonoPlay {
9 9 class MainClass {
10 10 public static void Main(string[] args) {
11 11 if (args == null)
12 12 throw new ArgumentNullException("args");
13 13
14 14 var q1 = new MTQueue<int>();
15 var q2 = new ConcurrentQueue<int>();
15 var q2 = new Queue<int>();
16 16
17 17 const int count = 10000000;
18 18
19 19 var t1 = Environment.TickCount;
20 20
21 21 for (var i = 0; i < count; i++)
22 22 q1.Enqueue(i);
23 23
24 24 var t2 = Environment.TickCount;
25 25 Console.WriteLine("MTQueue: {0} ms", t2 - t1);
26 26
27 27 t1 = Environment.TickCount;
28 28
29 29 for (var i = 0; i < count; i++)
30 30 q2.Enqueue(i);
31 31
32 32 t2 = Environment.TickCount;
33 33 Console.WriteLine("LinkedList: {0} ms", t2 - t1);
34 34
35 q2 = new ConcurrentQueue<int>();
35 q2 = new Queue<int>();
36 36
37 37 t1 = Environment.TickCount;
38 38
39 39 for (var i = 0; i < count; i++)
40 40 lock (q2)
41 41 q2.Enqueue(i);
42 42
43 43 t2 = Environment.TickCount;
44 44 Console.WriteLine("LinkedList+Lock: {0} ms", t2 - t1);
45 45
46 46 }
47 47 }
48 48 }
General Comments 0
You need to be logged in to leave comments. Login now