##// END OF EJS Templates
promises refactoring
cin -
r72:d67b95eddaf4 v2
parent child
Show More
@@ -0,0 +1,30
1 using System.Windows.Forms;
2 using System;
3
4
5 namespace Implab.Fx {
6 public class ControlBoundPromise<T> : Promise<T> {
7 readonly Control m_target;
8
9 public ControlBoundPromise(Control target) {
10 Safe.ArgumentNotNull(target, "target");
11
12 m_target = target;
13 }
14
15 public ControlBoundPromise(Control target, IPromise parent, bool cancellable)
16 : base(parent, cancellable) {
17 Safe.ArgumentNotNull(target, "target");
18
19 m_target = target;
20 }
21
22 protected override void InvokeHandler(HandlerDescriptor handler) {
23 if (m_target.InvokeRequired)
24 m_target.BeginInvoke(new Action<HandlerDescriptor>(base.InvokeHandler), handler);
25 else
26 base.InvokeHandler(handler);
27 }
28 }
29 }
30
@@ -0,0 +1,38
1 using System.Threading;
2
3 namespace Implab {
4 public static class PromiseExtensions {
5 public static IPromise<T> DispatchToCurrentContext<T>(this IPromise<T> that) {
6 var context = SynchronizationContext.Current;
7 if (context == null)
8 return that;
9
10 var p = new SyncContextPromise<T>(context, that, true);
11
12 that.Then(
13 x => p.Resolve(x),
14 e => {
15 p.Reject(e);
16 return default(T);
17 }
18 );
19 return p;
20 }
21
22 public static IPromise<T> DispatchToContext<T>(this IPromise<T> that, SynchronizationContext context) {
23 Safe.ArgumentNotNull(context, "context");
24
25 var p = new SyncContextPromise<T>(context, that, true);
26
27 that.Then(
28 x => p.Resolve(x),
29 e => {
30 p.Reject(e);
31 return default(T);
32 }
33 );
34 return p;
35 }
36 }
37 }
38
@@ -0,0 +1,22
1 using System.Threading;
2
3 namespace Implab {
4 public class SyncContextPromise<T> : Promise<T> {
5 readonly SynchronizationContext m_context;
6
7 public SyncContextPromise(SynchronizationContext context) {
8 Safe.ArgumentNotNull(context, "context");
9 m_context = context;
10 }
11
12 public SyncContextPromise(SynchronizationContext context, IPromise parent, bool cancellable)
13 : base(parent, cancellable) {
14 Safe.ArgumentNotNull(context, "context");
15 m_context = context;
16 }
17 protected override void InvokeHandler(HandlerDescriptor handler) {
18 m_context.Post(x => base.InvokeHandler(handler),null);
19 }
20 }
21 }
22
@@ -0,0 +1,33
1 using System;
2
3 namespace Implab {
4
5 [Serializable]
6 public class TransientPromiseException : Exception {
7 /// <summary>
8 /// Initializes a new instance of the <see cref="PromiseFailedException"/> class.
9 /// </summary>
10 /// <param name="inner">The exception that is the cause of the current exception.</param>
11 public TransientPromiseException(Exception inner) : base("The preceding promise has failed", inner) {
12 }
13
14 /// <summary>
15 /// Initializes a new instance of the <see cref="PromiseFailedException"/> class
16 /// </summary>
17 /// <param name="message">A <see cref="T:System.String"/> that describes the exception. </param>
18 /// <param name="inner">The exception that is the cause of the current exception. </param>
19 public TransientPromiseException(string message, Exception inner)
20 : base(message, inner) {
21 }
22
23 /// <summary>
24 /// Initializes a new instance of the <see cref="PromiseFailedException"/> class
25 /// </summary>
26 /// <param name="context">The contextual information about the source or destination.</param>
27 /// <param name="info">The object that holds the serialized object data.</param>
28 protected TransientPromiseException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
29 : base(info, context) {
30 }
31 }
32 }
33
@@ -1,94 +1,92
1 1 ο»Ώ<?xml version="1.0" encoding="utf-8"?>
2 2 <Project ToolsVersion="4.0" DefaultTargets="Build" 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 <ProductVersion>
7 </ProductVersion>
6 <ProductVersion>8.0.30703</ProductVersion>
8 7 <SchemaVersion>2.0</SchemaVersion>
9 8 <ProjectGuid>{2F31E405-E267-4195-A05D-574093C21209}</ProjectGuid>
10 9 <OutputType>Library</OutputType>
11 10 <AppDesignerFolder>Properties</AppDesignerFolder>
12 11 <RootNamespace>Implab.Fx.Test</RootNamespace>
13 12 <AssemblyName>Implab.Fx.Test</AssemblyName>
14 13 <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
15 14 <FileAlignment>512</FileAlignment>
16 15 <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
17 16 </PropertyGroup>
18 17 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
19 18 <DebugSymbols>true</DebugSymbols>
20 19 <DebugType>full</DebugType>
21 20 <Optimize>false</Optimize>
22 21 <OutputPath>bin\Debug\</OutputPath>
23 22 <DefineConstants>DEBUG;TRACE</DefineConstants>
24 23 <ErrorReport>prompt</ErrorReport>
25 24 <WarningLevel>4</WarningLevel>
26 25 </PropertyGroup>
27 26 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
28 27 <DebugType>pdbonly</DebugType>
29 28 <Optimize>true</Optimize>
30 29 <OutputPath>bin\Release\</OutputPath>
31 30 <DefineConstants>TRACE</DefineConstants>
32 31 <ErrorReport>prompt</ErrorReport>
33 32 <WarningLevel>4</WarningLevel>
34 33 </PropertyGroup>
35 34 <ItemGroup>
36 35 <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
37 36 <Reference Include="System" />
38 37 <Reference Include="System.Core">
39 38 <RequiredTargetFramework>3.5</RequiredTargetFramework>
40 39 </Reference>
41 40 <Reference Include="System.Data" />
42 41 <Reference Include="System.Drawing" />
43 42 <Reference Include="System.Windows.Forms" />
44 43 <Reference Include="System.Xml" />
45 44 <Reference Include="WindowsBase" />
46 45 </ItemGroup>
47 46 <ItemGroup>
48 <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
49 <Visible>False</Visible>
50 </CodeAnalysisDependentAssemblyPaths>
51 </ItemGroup>
52 <ItemGroup>
53 47 <Compile Include="Properties\AssemblyInfo.cs" />
54 48 <Compile Include="OverlayTest.cs" />
55 49 <Compile Include="Sample\MainForm.cs">
56 50 <SubType>Form</SubType>
57 51 </Compile>
58 52 <Compile Include="Sample\MainForm.Designer.cs">
59 53 <DependentUpon>MainForm.cs</DependentUpon>
60 54 </Compile>
61 55 <Compile Include="Sample\OverlayForm.cs">
62 56 <SubType>Form</SubType>
63 57 </Compile>
64 58 <Compile Include="Sample\OverlayForm.Designer.cs">
65 59 <DependentUpon>OverlayForm.cs</DependentUpon>
66 60 </Compile>
67 61 </ItemGroup>
68 62 <ItemGroup>
69 63 <EmbeddedResource Include="Sample\MainForm.resx">
70 64 <DependentUpon>MainForm.cs</DependentUpon>
65 <LogicalName>
66 </LogicalName>
71 67 </EmbeddedResource>
72 68 <EmbeddedResource Include="Sample\OverlayForm.resx">
73 69 <DependentUpon>OverlayForm.cs</DependentUpon>
70 <LogicalName>
71 </LogicalName>
74 72 </EmbeddedResource>
75 73 </ItemGroup>
76 74 <ItemGroup>
77 75 <ProjectReference Include="..\Implab.Fx\Implab.Fx.csproj">
78 76 <Project>{06E706F8-6881-43EB-927E-FFC503AF6ABC}</Project>
79 77 <Name>Implab.Fx</Name>
80 78 </ProjectReference>
81 79 <ProjectReference Include="..\Implab\Implab.csproj">
82 80 <Project>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</Project>
83 81 <Name>Implab</Name>
84 82 </ProjectReference>
85 83 </ItemGroup>
86 84 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
87 85 <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
88 86 Other similar extension points exist, see Microsoft.Common.targets.
89 87 <Target Name="BeforeBuild">
90 88 </Target>
91 89 <Target Name="AfterBuild">
92 90 </Target>
93 91 -->
94 92 </Project> No newline at end of file
@@ -1,64 +1,65
1 1 ο»Ώ<?xml version="1.0" encoding="utf-8"?>
2 2 <Project ToolsVersion="4.0" DefaultTargets="Build" 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 <ProductVersion>8.0.30703</ProductVersion>
7 7 <SchemaVersion>2.0</SchemaVersion>
8 8 <ProjectGuid>{06E706F8-6881-43EB-927E-FFC503AF6ABC}</ProjectGuid>
9 9 <OutputType>Library</OutputType>
10 10 <AppDesignerFolder>Properties</AppDesignerFolder>
11 11 <RootNamespace>Implab.Fx</RootNamespace>
12 12 <AssemblyName>Implab.Fx</AssemblyName>
13 13 <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
14 14 <FileAlignment>512</FileAlignment>
15 15 </PropertyGroup>
16 16 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
17 17 <DebugSymbols>true</DebugSymbols>
18 18 <DebugType>full</DebugType>
19 19 <Optimize>false</Optimize>
20 20 <OutputPath>bin\Debug\</OutputPath>
21 21 <DefineConstants>DEBUG;TRACE</DefineConstants>
22 22 <ErrorReport>prompt</ErrorReport>
23 23 <WarningLevel>4</WarningLevel>
24 24 </PropertyGroup>
25 25 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
26 26 <DebugType>pdbonly</DebugType>
27 27 <Optimize>true</Optimize>
28 28 <OutputPath>bin\Release\</OutputPath>
29 29 <DefineConstants>TRACE</DefineConstants>
30 30 <ErrorReport>prompt</ErrorReport>
31 31 <WarningLevel>4</WarningLevel>
32 32 </PropertyGroup>
33 33 <ItemGroup>
34 34 <Reference Include="System" />
35 35 <Reference Include="System.Core" />
36 36 <Reference Include="System.Drawing" />
37 37 <Reference Include="System.Windows.Forms" />
38 38 <Reference Include="System.Xml.Linq" />
39 39 <Reference Include="System.Data.DataSetExtensions" />
40 40 <Reference Include="Microsoft.CSharp" />
41 41 <Reference Include="System.Data" />
42 42 <Reference Include="System.Xml" />
43 43 </ItemGroup>
44 44 <ItemGroup>
45 45 <Compile Include="Animation.cs" />
46 46 <Compile Include="AnimationHelpers.cs" />
47 47 <Compile Include="PromiseHelpers.cs" />
48 48 <Compile Include="Properties\AssemblyInfo.cs" />
49 <Compile Include="ControlBoundPromise.cs" />
49 50 </ItemGroup>
50 51 <ItemGroup>
51 52 <ProjectReference Include="..\Implab\Implab.csproj">
52 <Project>{99B95D0D-9CF9-4F70-8ADF-F4D0AA5CB0D9}</Project>
53 <Project>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</Project>
53 54 <Name>Implab</Name>
54 55 </ProjectReference>
55 56 </ItemGroup>
56 57 <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
57 58 <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
58 59 Other similar extension points exist, see Microsoft.Common.targets.
59 60 <Target Name="BeforeBuild">
60 61 </Target>
61 62 <Target Name="AfterBuild">
62 63 </Target>
63 64 -->
64 65 </Project> No newline at end of file
@@ -1,95 +1,87
1 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 2 using System.Windows.Forms;
6 3 using System.Threading;
7 4
8 5 namespace Implab.Fx
9 6 {
10 7 public static class PromiseHelpers
11 8 {
12 9 /// <summary>
13 10 /// ΠŸΠ΅Ρ€Π΅Π½Π°ΠΏΡ€Π°Π²Π»ΡΠ΅Ρ‚ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ обСщания Π² ΠΏΠΎΡ‚ΠΎΠΊ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠ³ΠΎ элСмСнта управлСния.
14 11 /// </summary>
15 12 /// <typeparam name="T">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° обСщания</typeparam>
16 13 /// <param name="that">Π˜ΡΡ…ΠΎΠ΄Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅</param>
17 14 /// <param name="ctl">Π­Π»Π΅ΠΌΠ΅Π½Ρ‚ управлСния</param>
18 15 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Ρ‹ Π² ΠΏΠΎΡ‚ΠΎΠΊΠ΅ элСмСнта управлСния.</returns>
19 16 /// <exception cref="ArgumentNullException">ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ <c>null</c>.</exception>
20 17 /// <example>
21 18 /// client
22 19 /// .Get("description.txt") // returns a promise
23 20 /// .DirectToControl(m_ctl) // handle the promise in the thread of the control
24 21 /// .Then(
25 22 /// description => m_ctl.Text = description // now it's safe
26 23 /// )
27 24 /// </example>
28 25 public static Promise<T> DispatchToControl<T>(this Promise<T> that, Control ctl)
29 26 {
30 27 if (that == null)
31 28 throw new ArgumentNullException("that");
32 29 if (ctl == null)
33 30 throw new ArgumentNullException("ctl");
34 31
35 var directed = new Promise<T>();
32 var directed = new ControlBoundPromise<T>(ctl,that,true);
36 33
37 34 that.Then(
38 res =>
39 {
40 if (ctl.InvokeRequired)
41 ctl.Invoke(new Action<T>(directed.Resolve), res);
42 else
43 directed.Resolve(res);
44 },
35 directed.Resolve,
45 36 err =>
46 37 {
47 if (ctl.InvokeRequired)
48 ctl.Invoke(new Action<Exception>(directed.Reject), err);
49 else
50 directed.Reject(err);
38 directed.Reject(err);
39 return default(T);
51 40 }
52 41 );
53 42
54 43 return directed;
55 44 }
56 45
57 46 /// <summary>
58 47 /// НаправляСт ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ обСщания Π² Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ, Ссли Ρƒ Π½Π΅Π³ΠΎ сущСствуСт контСкст синхронизации.
59 48 /// </summary>
60 49 /// <typeparam name="T">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° обСщания.</typeparam>
61 50 /// <param name="that">ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π½ΡƒΠΆΠ½ΠΎ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ ΠΏΠΎΡ‚ΠΎΠΊΠ΅.</param>
62 51 /// <returns>ΠŸΠ΅Ρ€Π΅Π½Π°ΠΏΡ€Π°Π²Π»Π΅Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅.</returns>
63 52 public static Promise<T> DispatchToCurrentThread<T>(this Promise<T> that)
64 53 {
65 54 var sync = SynchronizationContext.Current;
66 55 if (sync == null)
67 56 throw new InvalidOperationException("The current thread doesn't have a syncronization context");
68 57 return DispatchToSyncContext(that, sync);
69 58 }
70 59
71 60 /// <summary>
72 61 /// НаправляСт ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ обСщания Π² ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΉ контСкст синхронизации.
73 62 /// </summary>
74 63 /// <typeparam name="T">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° обСщания.</typeparam>
75 64 /// <param name="that">ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ трСбуСтся ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΌ контСкстС синхронизации.</param>
76 65 /// <param name="sync">ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ синхронизации Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ Π½Π°ΠΏΡ€Π°Π²Π»Π΅Π½ΠΎ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅.</param>
77 66 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒΡΡ Π² ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΌ контСкстС.</returns>
78 67 public static Promise<T> DispatchToSyncContext<T>(this Promise<T> that, SynchronizationContext sync)
79 68 {
80 69 if (that == null)
81 70 throw new ArgumentNullException("that");
82 71 if (sync == null)
83 72 throw new ArgumentNullException("sync");
84 73
85 74 var d = new Promise<T>();
86 75
87 76 that.Then(
88 77 res => sync.Post(state => d.Resolve(res), null),
89 err => sync.Post(state => d.Reject(err), null)
78 err => {
79 sync.Post(state => d.Reject(err), null);
80 return default(T);
81 }
90 82 );
91 83
92 84 return d;
93 85 }
94 86 }
95 87 }
@@ -1,66 +1,60
1 1 ο»Ώ<?xml version="1.0" encoding="utf-8"?>
2 2 <Project ToolsVersion="4.0" DefaultTargets="Build" 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 <ProductVersion>
7 </ProductVersion>
6 <ProductVersion>8.0.30703</ProductVersion>
8 7 <SchemaVersion>2.0</SchemaVersion>
9 8 <ProjectGuid>{63F92C0C-61BF-48C0-A377-8D67C3C661D0}</ProjectGuid>
10 9 <OutputType>Library</OutputType>
11 10 <AppDesignerFolder>Properties</AppDesignerFolder>
12 11 <RootNamespace>Implab.Test</RootNamespace>
13 12 <AssemblyName>Implab.Test</AssemblyName>
14 13 <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
15 14 <FileAlignment>512</FileAlignment>
16 15 <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
17 16 </PropertyGroup>
18 17 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
19 18 <DebugSymbols>true</DebugSymbols>
20 19 <DebugType>full</DebugType>
21 20 <Optimize>false</Optimize>
22 21 <OutputPath>bin\Debug\</OutputPath>
23 22 <DefineConstants>DEBUG;TRACE</DefineConstants>
24 23 <ErrorReport>prompt</ErrorReport>
25 24 <WarningLevel>4</WarningLevel>
26 25 </PropertyGroup>
27 26 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
28 27 <DebugType>pdbonly</DebugType>
29 28 <Optimize>true</Optimize>
30 29 <OutputPath>bin\Release\</OutputPath>
31 30 <DefineConstants>TRACE</DefineConstants>
32 31 <ErrorReport>prompt</ErrorReport>
33 32 <WarningLevel>4</WarningLevel>
34 33 </PropertyGroup>
35 34 <ItemGroup>
36 35 <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
37 36 <Reference Include="System" />
38 37 <Reference Include="System.Core">
39 38 <RequiredTargetFramework>3.5</RequiredTargetFramework>
40 39 </Reference>
41 40 </ItemGroup>
42 41 <ItemGroup>
43 <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
44 <Visible>False</Visible>
45 </CodeAnalysisDependentAssemblyPaths>
46 </ItemGroup>
47 <ItemGroup>
48 42 <Compile Include="AsyncTests.cs" />
49 43 <Compile Include="PromiseHelper.cs" />
50 44 <Compile Include="Properties\AssemblyInfo.cs" />
51 45 </ItemGroup>
52 46 <ItemGroup>
53 47 <ProjectReference Include="..\Implab\Implab.csproj">
54 48 <Project>{99B95D0D-9CF9-4F70-8ADF-F4D0AA5CB0D9}</Project>
55 49 <Name>Implab</Name>
56 50 </ProjectReference>
57 51 </ItemGroup>
58 52 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
59 53 <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
60 54 Other similar extension points exist, see Microsoft.Common.targets.
61 55 <Target Name="BeforeBuild">
62 56 </Target>
63 57 <Target Name="AfterBuild">
64 58 </Target>
65 59 -->
66 60 </Project> No newline at end of file
@@ -1,51 +1,252
1 1 ο»Ώ
2 2 Microsoft Visual Studio Solution File, Format Version 11.00
3 3 # Visual Studio 2010
4 4 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab", "Implab\Implab.csproj", "{F550F1F8-8746-4AD0-9614-855F4C4B7F05}"
5 5 EndProject
6 6 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{CE8D8D18-437A-445C-B662-4C2CE79A76F6}"
7 7 ProjectSection(SolutionItems) = preProject
8 8 Implab.vsmdi = Implab.vsmdi
9 9 Local.testsettings = Local.testsettings
10 10 TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings
11 11 EndProjectSection
12 12 EndProject
13 13 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Test", "Implab.Test\Implab.Test.csproj", "{63F92C0C-61BF-48C0-A377-8D67C3C661D0}"
14 14 EndProject
15 15 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Fx", "Implab.Fx\Implab.Fx.csproj", "{06E706F8-6881-43EB-927E-FFC503AF6ABC}"
16 16 EndProject
17 17 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Fx.Test", "Implab.Fx.Test\Implab.Fx.Test.csproj", "{2F31E405-E267-4195-A05D-574093C21209}"
18 18 EndProject
19 19 Global
20 GlobalSection(TestCaseManagementSettings) = postSolution
21 CategoryFile = Implab.vsmdi
22 EndGlobalSection
23 20 GlobalSection(SolutionConfigurationPlatforms) = preSolution
24 21 Debug|Any CPU = Debug|Any CPU
25 22 Release|Any CPU = Release|Any CPU
26 23 EndGlobalSection
27 24 GlobalSection(ProjectConfigurationPlatforms) = postSolution
28 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release|Any CPU.Build.0 = Release|Any CPU
32 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release|Any CPU.Build.0 = Release|Any CPU
36 25 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 26 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 27 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release|Any CPU.ActiveCfg = Release|Any CPU
39 28 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release|Any CPU.Build.0 = Release|Any CPU
40 29 {2F31E405-E267-4195-A05D-574093C21209}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
41 30 {2F31E405-E267-4195-A05D-574093C21209}.Debug|Any CPU.Build.0 = Debug|Any CPU
42 31 {2F31E405-E267-4195-A05D-574093C21209}.Release|Any CPU.ActiveCfg = Release|Any CPU
43 32 {2F31E405-E267-4195-A05D-574093C21209}.Release|Any CPU.Build.0 = Release|Any CPU
33 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
34 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
35 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
36 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release|Any CPU.Build.0 = Release|Any CPU
37 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
38 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug|Any CPU.Build.0 = Debug|Any CPU
39 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release|Any CPU.ActiveCfg = Release|Any CPU
40 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release|Any CPU.Build.0 = Release|Any CPU
41 EndGlobalSection
42 GlobalSection(NestedProjects) = preSolution
43 EndGlobalSection
44 GlobalSection(MonoDevelopProperties) = preSolution
45 StartupItem = Implab\Implab.csproj
46 Policies = $0
47 $0.CSharpFormattingPolicy = $1
48 $1.IndentSwitchBody = True
49 $1.NamespaceBraceStyle = EndOfLine
50 $1.ClassBraceStyle = EndOfLine
51 $1.InterfaceBraceStyle = EndOfLine
52 $1.StructBraceStyle = EndOfLine
53 $1.EnumBraceStyle = EndOfLine
54 $1.MethodBraceStyle = EndOfLine
55 $1.ConstructorBraceStyle = EndOfLine
56 $1.DestructorBraceStyle = EndOfLine
57 $1.BeforeMethodDeclarationParentheses = False
58 $1.BeforeMethodCallParentheses = False
59 $1.BeforeConstructorDeclarationParentheses = False
60 $1.NewLineBeforeConstructorInitializerColon = NewLine
61 $1.NewLineAfterConstructorInitializerColon = SameLine
62 $1.BeforeIndexerDeclarationBracket = False
63 $1.BeforeDelegateDeclarationParentheses = False
64 $1.NewParentheses = False
65 $1.SpacesBeforeBrackets = False
66 $1.inheritsSet = Mono
67 $1.inheritsScope = text/x-csharp
68 $1.scope = text/x-csharp
69 $0.TextStylePolicy = $2
70 $2.FileWidth = 120
71 $2.EolMarker = Unix
72 $2.inheritsSet = VisualStudio
73 $2.inheritsScope = text/plain
74 $2.scope = text/x-csharp
75 $0.DotNetNamingPolicy = $3
76 $3.DirectoryNamespaceAssociation = PrefixedHierarchical
77 $3.ResourceNamePolicy = MSBuild
78 $0.TextStylePolicy = $4
79 $4.FileWidth = 120
80 $4.TabsToSpaces = False
81 $4.inheritsSet = VisualStudio
82 $4.inheritsScope = text/plain
83 $4.scope = application/xml
84 $0.XmlFormattingPolicy = $5
85 $5.inheritsSet = Mono
86 $5.inheritsScope = application/xml
87 $5.scope = application/xml
88 $0.TextStylePolicy = $6
89 $6.FileWidth = 120
90 $6.TabsToSpaces = False
91 $6.inheritsSet = VisualStudio
92 $6.inheritsScope = text/plain
93 $6.scope = text/plain
94 $0.NameConventionPolicy = $7
95 $7.Rules = $8
96 $8.NamingRule = $9
97 $9.Name = Namespaces
98 $9.AffectedEntity = Namespace
99 $9.VisibilityMask = VisibilityMask
100 $9.NamingStyle = PascalCase
101 $9.IncludeInstanceMembers = True
102 $9.IncludeStaticEntities = True
103 $8.NamingRule = $10
104 $10.Name = Types
105 $10.AffectedEntity = Class, Struct, Enum, Delegate
106 $10.VisibilityMask = VisibilityMask
107 $10.NamingStyle = PascalCase
108 $10.IncludeInstanceMembers = True
109 $10.IncludeStaticEntities = True
110 $8.NamingRule = $11
111 $11.Name = Interfaces
112 $11.RequiredPrefixes = $12
113 $12.String = I
114 $11.AffectedEntity = Interface
115 $11.VisibilityMask = VisibilityMask
116 $11.NamingStyle = PascalCase
117 $11.IncludeInstanceMembers = True
118 $11.IncludeStaticEntities = True
119 $8.NamingRule = $13
120 $13.Name = Attributes
121 $13.RequiredSuffixes = $14
122 $14.String = Attribute
123 $13.AffectedEntity = CustomAttributes
124 $13.VisibilityMask = VisibilityMask
125 $13.NamingStyle = PascalCase
126 $13.IncludeInstanceMembers = True
127 $13.IncludeStaticEntities = True
128 $8.NamingRule = $15
129 $15.Name = Event Arguments
130 $15.RequiredSuffixes = $16
131 $16.String = EventArgs
132 $15.AffectedEntity = CustomEventArgs
133 $15.VisibilityMask = VisibilityMask
134 $15.NamingStyle = PascalCase
135 $15.IncludeInstanceMembers = True
136 $15.IncludeStaticEntities = True
137 $8.NamingRule = $17
138 $17.Name = Exceptions
139 $17.RequiredSuffixes = $18
140 $18.String = Exception
141 $17.AffectedEntity = CustomExceptions
142 $17.VisibilityMask = VisibilityMask
143 $17.NamingStyle = PascalCase
144 $17.IncludeInstanceMembers = True
145 $17.IncludeStaticEntities = True
146 $8.NamingRule = $19
147 $19.Name = Methods
148 $19.AffectedEntity = Methods
149 $19.VisibilityMask = VisibilityMask
150 $19.NamingStyle = PascalCase
151 $19.IncludeInstanceMembers = True
152 $19.IncludeStaticEntities = True
153 $8.NamingRule = $20
154 $20.Name = Static Readonly Fields
155 $20.AffectedEntity = ReadonlyField
156 $20.VisibilityMask = Internal, Protected, Public
157 $20.NamingStyle = CamelCase
158 $20.IncludeInstanceMembers = False
159 $20.IncludeStaticEntities = True
160 $8.NamingRule = $21
161 $21.Name = Fields (Non Private)
162 $21.AffectedEntity = Field
163 $21.VisibilityMask = Internal, Public
164 $21.NamingStyle = CamelCase
165 $21.IncludeInstanceMembers = True
166 $21.IncludeStaticEntities = True
167 $8.NamingRule = $22
168 $22.Name = ReadOnly Fields (Non Private)
169 $22.AffectedEntity = ReadonlyField
170 $22.VisibilityMask = Internal, Public
171 $22.NamingStyle = CamelCase
172 $22.IncludeInstanceMembers = True
173 $22.IncludeStaticEntities = False
174 $8.NamingRule = $23
175 $23.Name = Fields (Private)
176 $23.RequiredPrefixes = $24
177 $24.String = m_
178 $23.AffectedEntity = Field, ReadonlyField
179 $23.VisibilityMask = Private, Protected
180 $23.NamingStyle = CamelCase
181 $23.IncludeInstanceMembers = True
182 $23.IncludeStaticEntities = False
183 $8.NamingRule = $25
184 $25.Name = Static Fields (Private)
185 $25.RequiredPrefixes = $26
186 $26.String = _
187 $25.AffectedEntity = Field
188 $25.VisibilityMask = Private
189 $25.NamingStyle = CamelCase
190 $25.IncludeInstanceMembers = False
191 $25.IncludeStaticEntities = True
192 $8.NamingRule = $27
193 $27.Name = ReadOnly Fields (Private)
194 $27.RequiredPrefixes = $28
195 $28.String = m_
196 $27.AffectedEntity = ReadonlyField
197 $27.VisibilityMask = Private, Protected
198 $27.NamingStyle = CamelCase
199 $27.IncludeInstanceMembers = True
200 $27.IncludeStaticEntities = False
201 $8.NamingRule = $29
202 $29.Name = Constant Fields
203 $29.AffectedEntity = ConstantField
204 $29.VisibilityMask = VisibilityMask
205 $29.NamingStyle = AllUpper
206 $29.IncludeInstanceMembers = True
207 $29.IncludeStaticEntities = True
208 $8.NamingRule = $30
209 $30.Name = Properties
210 $30.AffectedEntity = Property
211 $30.VisibilityMask = VisibilityMask
212 $30.NamingStyle = PascalCase
213 $30.IncludeInstanceMembers = True
214 $30.IncludeStaticEntities = True
215 $8.NamingRule = $31
216 $31.Name = Events
217 $31.AffectedEntity = Event
218 $31.VisibilityMask = VisibilityMask
219 $31.NamingStyle = PascalCase
220 $31.IncludeInstanceMembers = True
221 $31.IncludeStaticEntities = True
222 $8.NamingRule = $32
223 $32.Name = Enum Members
224 $32.AffectedEntity = EnumMember
225 $32.VisibilityMask = VisibilityMask
226 $32.NamingStyle = PascalCase
227 $32.IncludeInstanceMembers = True
228 $32.IncludeStaticEntities = True
229 $8.NamingRule = $33
230 $33.Name = Parameters
231 $33.AffectedEntity = Parameter, LocalVariable
232 $33.VisibilityMask = VisibilityMask
233 $33.NamingStyle = CamelCase
234 $33.IncludeInstanceMembers = True
235 $33.IncludeStaticEntities = True
236 $8.NamingRule = $34
237 $34.Name = Type Parameters
238 $34.RequiredPrefixes = $35
239 $35.String = T
240 $34.AffectedEntity = TypeParameter
241 $34.VisibilityMask = VisibilityMask
242 $34.NamingStyle = PascalCase
243 $34.IncludeInstanceMembers = True
244 $34.IncludeStaticEntities = True
245 EndGlobalSection
246 GlobalSection(TestCaseManagementSettings) = postSolution
247 CategoryFile = Implab.vsmdi
44 248 EndGlobalSection
45 249 GlobalSection(SolutionProperties) = preSolution
46 250 HideSolutionNode = FALSE
47 251 EndGlobalSection
48 GlobalSection(MonoDevelopProperties) = preSolution
49 StartupItem = Implab\Implab.csproj
50 EndGlobalSection
51 252 EndGlobal
@@ -1,31 +1,29
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 {
8 8 public interface IPromise<T>: IPromise
9 9 {
10 10
11 11 new T Join();
12 12 new T Join(int timeout);
13 13
14 IPromise<T> Then(ResultHandler<T> success, ErrorHandler error);
15 14 IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error);
16 15 IPromise<T> Then(ResultHandler<T> success);
17 new IPromise<T> Error(ErrorHandler error);
18 16 IPromise<T> Error(ErrorHandler<T> error);
19 17
20 IPromise<T2> Map<T2>(ResultMapper<T,T2> mapper, ErrorHandler error);
18 IPromise<T2> Map<T2>(ResultMapper<T,T2> mapper, ErrorHandler<T> error);
21 19 IPromise<T2> Map<T2>(ResultMapper<T, T2> mapper);
22 20
23 IPromise<T2> Chain<T2>(ChainedOperation<T, T2> chained, ErrorHandler error);
21 IPromise<T2> Chain<T2>(ChainedOperation<T, T2> chained, ErrorHandler<T> error);
24 22 IPromise<T2> Chain<T2>(ChainedOperation<T, T2> chained);
25 23
26 24 new IPromise<T> Cancelled(Action handler);
27 25 new IPromise<T> Finally(Action handler);
28 26 new IPromise<T> Anyway(Action handler);
29 27
30 28 }
31 29 }
@@ -1,105 +1,179
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 <ProductVersion>8.0.30703</ProductVersion>
11 <SchemaVersion>2.0</SchemaVersion>
10 12 </PropertyGroup>
11 13 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
12 14 <DebugSymbols>true</DebugSymbols>
13 15 <DebugType>full</DebugType>
14 16 <Optimize>false</Optimize>
15 17 <OutputPath>bin\Debug</OutputPath>
16 18 <DefineConstants>TRACE;DEBUG;</DefineConstants>
17 19 <ErrorReport>prompt</ErrorReport>
18 20 <WarningLevel>4</WarningLevel>
19 21 <ConsolePause>false</ConsolePause>
20 22 <RunCodeAnalysis>true</RunCodeAnalysis>
21 23 </PropertyGroup>
22 24 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
23 25 <DebugType>full</DebugType>
24 26 <Optimize>true</Optimize>
25 27 <OutputPath>bin\Release</OutputPath>
26 28 <ErrorReport>prompt</ErrorReport>
27 29 <WarningLevel>4</WarningLevel>
28 30 <ConsolePause>false</ConsolePause>
29 31 </PropertyGroup>
30 32 <ItemGroup>
31 33 <Reference Include="System" />
32 34 <Reference Include="System.Xml" />
33 35 </ItemGroup>
34 36 <ItemGroup>
35 37 <Compile Include="Component.cs" />
36 38 <Compile Include="CustomEqualityComparer.cs" />
37 39 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
38 40 <Compile Include="Diagnostics\EventText.cs" />
39 41 <Compile Include="Diagnostics\IEventTextFormatter.cs" />
40 42 <Compile Include="Diagnostics\LogChannel.cs" />
41 43 <Compile Include="Diagnostics\LogicalOperation.cs" />
42 44 <Compile Include="Diagnostics\TextFileListener.cs" />
43 45 <Compile Include="Diagnostics\TextListenerBase.cs" />
44 46 <Compile Include="Diagnostics\TraceLog.cs" />
45 47 <Compile Include="Diagnostics\TraceContext.cs" />
46 48 <Compile Include="Diagnostics\TraceEvent.cs" />
47 49 <Compile Include="Diagnostics\TraceEventType.cs" />
48 50 <Compile Include="Disposable.cs" />
49 51 <Compile Include="ICancellable.cs" />
50 52 <Compile Include="IProgressHandler.cs" />
51 53 <Compile Include="IProgressNotifier.cs" />
52 54 <Compile Include="IPromiseT.cs" />
53 55 <Compile Include="IPromise.cs" />
54 56 <Compile Include="IServiceLocator.cs" />
55 57 <Compile Include="ITaskController.cs" />
56 58 <Compile Include="JSON\JSONElementContext.cs" />
57 59 <Compile Include="JSON\JSONElementType.cs" />
58 60 <Compile Include="JSON\JSONGrammar.cs" />
59 61 <Compile Include="JSON\JSONParser.cs" />
60 62 <Compile Include="JSON\JSONScanner.cs" />
61 63 <Compile Include="JSON\JsonTokenType.cs" />
62 64 <Compile Include="JSON\JSONWriter.cs" />
63 65 <Compile Include="JSON\JSONXmlReader.cs" />
64 66 <Compile Include="JSON\JSONXmlReaderOptions.cs" />
65 67 <Compile Include="JSON\StringTranslator.cs" />
66 68 <Compile Include="Parallels\DispatchPool.cs" />
67 69 <Compile Include="Parallels\ArrayTraits.cs" />
68 70 <Compile Include="Parallels\MTQueue.cs" />
69 71 <Compile Include="Parallels\WorkerPool.cs" />
70 72 <Compile Include="Parsing\Alphabet.cs" />
71 73 <Compile Include="Parsing\AlphabetBase.cs" />
72 74 <Compile Include="Parsing\AltToken.cs" />
73 75 <Compile Include="Parsing\BinaryToken.cs" />
74 76 <Compile Include="Parsing\CatToken.cs" />
75 77 <Compile Include="Parsing\CDFADefinition.cs" />
76 78 <Compile Include="Parsing\DFABuilder.cs" />
77 79 <Compile Include="Parsing\DFADefinitionBase.cs" />
78 80 <Compile Include="Parsing\DFAStateDescriptor.cs" />
79 81 <Compile Include="Parsing\DFAutomaton.cs" />
80 82 <Compile Include="Parsing\EDFADefinition.cs" />
81 83 <Compile Include="Parsing\EmptyToken.cs" />
82 84 <Compile Include="Parsing\EndToken.cs" />
83 85 <Compile Include="Parsing\EnumAlphabet.cs" />
84 86 <Compile Include="Parsing\Grammar.cs" />
85 87 <Compile Include="Parsing\IAlphabet.cs" />
86 88 <Compile Include="Parsing\IDFADefinition.cs" />
87 89 <Compile Include="Parsing\IVisitor.cs" />
88 90 <Compile Include="Parsing\ParserException.cs" />
89 91 <Compile Include="Parsing\Scanner.cs" />
90 92 <Compile Include="Parsing\StarToken.cs" />
91 93 <Compile Include="Parsing\SymbolToken.cs" />
92 94 <Compile Include="Parsing\Token.cs" />
93 95 <Compile Include="SafePool.cs" />
94 96 <Compile Include="ServiceLocator.cs" />
95 97 <Compile Include="TaskController.cs" />
96 98 <Compile Include="ProgressInitEventArgs.cs" />
97 99 <Compile Include="Properties\AssemblyInfo.cs" />
98 100 <Compile Include="Promise.cs" />
99 101 <Compile Include="Parallels\AsyncPool.cs" />
100 102 <Compile Include="Safe.cs" />
101 103 <Compile Include="ValueEventArgs.cs" />
104 <Compile Include="PromiseExtensions.cs" />
105 <Compile Include="TransientPromiseException.cs" />
106 <Compile Include="SyncContextPromise.cs" />
102 107 </ItemGroup>
103 108 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
104 109 <ItemGroup />
110 <ProjectExtensions>
111 <MonoDevelop>
112 <Properties>
113 <Policies>
114 <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" />
115 <TextStylePolicy FileWidth="120" EolMarker="Unix" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
116 <DotNetNamingPolicy DirectoryNamespaceAssociation="PrefixedHierarchical" ResourceNamePolicy="MSBuild" />
117 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="application/xml" />
118 <XmlFormattingPolicy inheritsSet="Mono" inheritsScope="application/xml" scope="application/xml" />
119 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" />
120 <NameConventionPolicy>
121 <Rules>
122 <NamingRule Name="Namespaces" AffectedEntity="Namespace" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
123 <NamingRule Name="Types" AffectedEntity="Class, Struct, Enum, Delegate" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
124 <NamingRule Name="Interfaces" AffectedEntity="Interface" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
125 <RequiredPrefixes>
126 <String>I</String>
127 </RequiredPrefixes>
128 </NamingRule>
129 <NamingRule Name="Attributes" AffectedEntity="CustomAttributes" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
130 <RequiredSuffixes>
131 <String>Attribute</String>
132 </RequiredSuffixes>
133 </NamingRule>
134 <NamingRule Name="Event Arguments" AffectedEntity="CustomEventArgs" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
135 <RequiredSuffixes>
136 <String>EventArgs</String>
137 </RequiredSuffixes>
138 </NamingRule>
139 <NamingRule Name="Exceptions" AffectedEntity="CustomExceptions" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
140 <RequiredSuffixes>
141 <String>Exception</String>
142 </RequiredSuffixes>
143 </NamingRule>
144 <NamingRule Name="Methods" AffectedEntity="Methods" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
145 <NamingRule Name="Static Readonly Fields" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Protected, Public" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True" />
146 <NamingRule Name="Fields (Non Private)" AffectedEntity="Field" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
147 <NamingRule Name="ReadOnly Fields (Non Private)" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False" />
148 <NamingRule Name="Fields (Private)" AffectedEntity="Field, ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
149 <RequiredPrefixes>
150 <String>m_</String>
151 </RequiredPrefixes>
152 </NamingRule>
153 <NamingRule Name="Static Fields (Private)" AffectedEntity="Field" VisibilityMask="Private" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True">
154 <RequiredPrefixes>
155 <String>_</String>
156 </RequiredPrefixes>
157 </NamingRule>
158 <NamingRule Name="ReadOnly Fields (Private)" AffectedEntity="ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
159 <RequiredPrefixes>
160 <String>m_</String>
161 </RequiredPrefixes>
162 </NamingRule>
163 <NamingRule Name="Constant Fields" AffectedEntity="ConstantField" VisibilityMask="VisibilityMask" NamingStyle="AllUpper" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
164 <NamingRule Name="Properties" AffectedEntity="Property" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
165 <NamingRule Name="Events" AffectedEntity="Event" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
166 <NamingRule Name="Enum Members" AffectedEntity="EnumMember" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
167 <NamingRule Name="Parameters" AffectedEntity="Parameter, LocalVariable" VisibilityMask="VisibilityMask" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
168 <NamingRule Name="Type Parameters" AffectedEntity="TypeParameter" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
169 <RequiredPrefixes>
170 <String>T</String>
171 </RequiredPrefixes>
172 </NamingRule>
173 </Rules>
174 </NameConventionPolicy>
175 </Policies>
176 </Properties>
177 </MonoDevelop>
178 </ProjectExtensions>
105 179 </Project> No newline at end of file
@@ -1,113 +1,103
1 1 using Implab.Parsing;
2 2 using System;
3 3 using System.Collections.Generic;
4 4 using System.Linq;
5 5 using System.Text;
6 6 using System.Threading.Tasks;
7 7
8 8 namespace Implab.JSON {
9 9 internal class JSONGrammar : Grammar<JSONGrammar> {
10 public enum TokenType : int{
10 public enum TokenType : int {
11 11 None,
12 12 BeginObject,
13 13 EndObject,
14 14 BeginArray,
15 15 EndArray,
16 16 String,
17 17 Number,
18 18 Literal,
19 19 NameSeparator,
20 20 ValueSeparator,
21 21
22 22 StringBound,
23 23 EscapedChar,
24 24 UnescapedChar,
25 25 EscapedUnicode,
26 26
27 27 Minus,
28 28 Plus,
29 29 Sign,
30 30 Integer,
31 31 Dot,
32 32 Exp
33 33 }
34 34
35 35 readonly CDFADefinition m_jsonDFA;
36 36 readonly CDFADefinition m_stringDFA;
37 37
38 38 public JSONGrammar() {
39 39 DefineAlphabet(Enumerable.Range(0, 0x20).Select(x => (char)x));
40 40 var hexDigit = SymbolRangeToken('a','f').Or(SymbolRangeToken('A','F')).Or(SymbolRangeToken('0','9'));
41 41 var digit9 = SymbolRangeToken('1', '9');
42 42 var zero = SymbolToken('0');
43 43 var digit = zero.Or(digit9);
44 44 var dot = SymbolToken('.');
45 45 var minus = SymbolToken('-');
46 46 var sign = SymbolSetToken('-', '+');
47 47 var expSign = SymbolSetToken('e', 'E');
48 48 var letters = SymbolRangeToken('a', 'z');
49 49 var integer = zero.Or(digit9.Cat(digit.EClosure()));
50 50 var frac = dot.Cat(digit.Closure());
51 51 var exp = expSign.Cat(sign.Optional()).Cat(digit.Closure());
52 52 var quote = SymbolToken('"');
53 53 var backSlash = SymbolToken('\\');
54 54 var specialEscapeChars = SymbolSetToken('\\', '"', '/', 'b', 'f', 't', 'n', 'r');
55 55 var unicodeEspace = SymbolToken('u').Cat(hexDigit.Repeat(4));
56 var escape = backSlash.Cat(specialEscapeChars.Or(unicodeEspace));
57 56 var whitespace = SymbolSetToken('\n', '\r', '\t', ' ').EClosure();
58 57 var beginObject = whitespace.Cat(SymbolToken('{')).Cat(whitespace);
59 58 var endObject = whitespace.Cat(SymbolToken('}')).Cat(whitespace);
60 59 var beginArray = whitespace.Cat(SymbolToken('[')).Cat(whitespace);
61 60 var endArray = whitespace.Cat(SymbolToken(']')).Cat(whitespace);
62 61 var nameSep = whitespace.Cat(SymbolToken(':')).Cat(whitespace);
63 62 var valueSep = whitespace.Cat(SymbolToken(',')).Cat(whitespace);
64 63
65 64 var number = minus.Optional().Cat(integer).Cat(frac.Optional()).Cat(exp.Optional());
66 65 var literal = letters.Closure();
67 66 var unescaped = SymbolTokenExcept(Enumerable.Range(0, 0x20).Union(new int[] { '\\', '"' }).Select(x => (char)x));
68 var character = unescaped.Or(escape);
69 var str = quote.Cat(character.EClosure()).Cat(quote);
70
71 67
72 68 var jsonExpression =
73 69 number.Tag(TokenType.Number)
74 70 .Or(literal.Tag(TokenType.Literal))
75 71 .Or(quote.Tag(TokenType.StringBound))
76 72 .Or(beginObject.Tag(TokenType.BeginObject))
77 73 .Or(endObject.Tag(TokenType.EndObject))
78 74 .Or(beginArray.Tag(TokenType.BeginArray))
79 75 .Or(endArray.Tag(TokenType.EndArray))
80 76 .Or(nameSep.Tag(TokenType.NameSeparator))
81 77 .Or(valueSep.Tag(TokenType.ValueSeparator));
82 78
83 79
84 80 var jsonStringExpression =
85 81 quote.Tag(TokenType.StringBound)
86 82 .Or(backSlash.Cat(specialEscapeChars).Tag(TokenType.EscapedChar))
87 83 .Or(backSlash.Cat(unicodeEspace).Tag(TokenType.EscapedUnicode))
88 84 .Or(unescaped.Closure().Tag(TokenType.UnescapedChar));
89
90 var jsonNumberExpression =
91 minus.Tag(TokenType.Minus)
92 .Or(SymbolToken('+').Tag(TokenType.Plus))
93 .Or(digit.Closure().Tag(TokenType.Integer))
94 .Or(dot.Tag(TokenType.Dot))
95 .Or(expSign.Tag(TokenType.Exp));
85
96 86
97 87 m_jsonDFA = BuildDFA(jsonExpression);
98 88 m_stringDFA = BuildDFA(jsonStringExpression);
99 89 }
100 90
101 91 public CDFADefinition JsonDFA {
102 92 get {
103 93 return m_jsonDFA;
104 94 }
105 95 }
106 96
107 97 public CDFADefinition JsonStringDFA {
108 98 get {
109 99 return m_stringDFA;
110 100 }
111 101 }
112 102 }
113 103 }
@@ -1,227 +1,256
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.IO;
4 4 using System.Linq;
5 5 using System.Text;
6 6 using System.Threading.Tasks;
7 7
8 8 namespace Implab.JSON {
9 9 public class JSONWriter {
10 10 struct Context {
11 11 public bool needComma;
12 12 public JSONElementContext element;
13 13 }
14 14 Stack<Context> m_contextStack = new Stack<Context>();
15 15 Context m_context;
16 16
17 17 TextWriter m_writer;
18 bool m_indent;
18 readonly bool m_indent = true;
19 readonly int m_indentSize = 4;
19 20
20 21 static readonly char [] _escapeBKS,
21 22 _escapeFWD,
22 23 _escapeCR,
23 24 _escapeNL,
24 25 _escapeTAB,
25 26 _escapeSLASH,
26 27 _escapeBSLASH,
27 28 _escapeQ;
28 29
29 30 static JSONWriter() {
30 31 _escapeBKS = "\\b".ToCharArray();
31 32 _escapeFWD = "\\f".ToCharArray();
32 33 _escapeCR = "\\r".ToCharArray();
33 34 _escapeNL = "\\n".ToCharArray();
34 35 _escapeTAB = "\\t".ToCharArray();
35 36 _escapeBSLASH = "\\\\".ToCharArray();
36 37 _escapeSLASH = "\\/".ToCharArray();
37 38 _escapeQ = "\\\"".ToCharArray();
38 39 }
39 40
40 41 public JSONWriter(TextWriter writer) {
41 42 Safe.ArgumentNotNull(writer, "writer");
42 43
43 44 m_writer = writer;
44 45 }
45 46
47 public JSONWriter(TextWriter writer, bool indent) {
48 Safe.ArgumentNotNull(writer, "writer");
49
50 m_writer = writer;
51 m_indent = indent;
52 }
53
54 void WriteIndent() {
55 if (m_indent) {
56 var indent = new char[m_contextStack.Count * m_indentSize + 1];
57 indent[0] = '\n';
58 for (int i = 1; i < indent.Length; i++)
59 indent[i] = ' ';
60 m_writer.Write(new String(indent));
61 } else {
62 m_writer.Write(' ');
63 }
64 }
65
46 66 void WriteMemberName(string name) {
47 67 Safe.ArgumentNotEmpty(name, "name");
48 68 if (m_context.element != JSONElementContext.Object)
49 69 OperationNotApplicable("WriteMember");
50 70 if (m_context.needComma)
51 m_writer.Write(", ");
52 // TODO indent
71 m_writer.Write(",");
72
73 WriteIndent();
53 74 m_context.needComma = true;
54 75 Write(name);
55 76 m_writer.Write(" : ");
56 77 }
57 78
58 79 public void WriteValue(string name, string value) {
59 80 WriteMemberName(name);
60 81 Write(value);
61 82 }
62 83
63 84 public void WriteValue(string name, bool value) {
64 85 WriteMemberName(name);
65 86 Write(value);
66 87 }
67 88
68 89 public void WriteValue(string name, double value) {
69 90 WriteMemberName(name);
70 91 Write(value);
71 92 }
72 93
73
74
75 94 public void WriteValue(string value) {
76 95 if (m_context.element != JSONElementContext.Array)
77 96 OperationNotApplicable("WriteValue");
78 97 if (m_context.needComma)
79 m_writer.Write(", ");
98 m_writer.Write(",");
99 WriteIndent();
80 100 m_context.needComma = true;
81 101
82 102 Write(value);
83 103 }
84 104
85 105 public void WriteValue(bool value) {
86 106 if (m_context.element != JSONElementContext.Array)
87 107 OperationNotApplicable("WriteValue");
88 108 if (m_context.needComma)
89 m_writer.Write(", ");
109 m_writer.Write(",");
90 110 m_context.needComma = true;
91 111
112 WriteIndent();
92 113 Write(value);
93 114 }
94 115
95 116 public void WriteValue(double value) {
96 117 if (m_context.element != JSONElementContext.Array)
97 118 OperationNotApplicable("WriteValue");
98 119 if (m_context.needComma)
99 m_writer.Write(", ");
120 m_writer.Write(",");
100 121 m_context.needComma = true;
101 122
123 WriteIndent();
102 124 Write(value);
103 125 }
104 126
105 127 public void BeginObject() {
106 128 if (m_context.element != JSONElementContext.None && m_context.element != JSONElementContext.Array)
107 129 OperationNotApplicable("BeginObject");
108 130 if (m_context.needComma)
109 m_writer.Write(", ");
131 m_writer.Write(",");
132
133 WriteIndent();
134
110 135 m_context.needComma = true;
111 136
112 137 m_contextStack.Push(m_context);
113 138
114 139 m_context = new Context { element = JSONElementContext.Object, needComma = false };
115 m_writer.Write("{ ");
140 m_writer.Write("{");
116 141 }
117 142
118 143 public void BeginObject(string name) {
119 144 WriteMemberName(name);
120 145
121 146 m_contextStack.Push(m_context);
122 147
123 148 m_context = new Context { element = JSONElementContext.Object, needComma = false };
124 m_writer.Write("{ ");
149 m_writer.Write("{");
125 150 }
126 151
127 152 public void EndObject() {
128 153 if (m_context.element != JSONElementContext.Object)
129 154 OperationNotApplicable("EndArray");
130
131 m_writer.Write(" }");
155
132 156 m_context = m_contextStack.Pop();
157 WriteIndent();
158 m_writer.Write("}");
133 159 }
134 160
135 161 public void BeginArray() {
136 162 if (m_context.element != JSONElementContext.None && m_context.element != JSONElementContext.Array)
137 163 throw new InvalidOperationException();
138 if (m_context.needComma)
139 m_writer.Write(", ");
164 if (m_context.needComma) {
165 m_writer.Write(",");
166
167 }
140 168 m_context.needComma = true;
141 169
170 WriteIndent();
142 171 m_contextStack.Push(m_context);
143
144 172 m_context = new Context { element = JSONElementContext.Array, needComma = false };
145 m_writer.Write("[ ");
173 m_writer.Write("[");
146 174 }
147 175
148 176 public void BeginArray(string name) {
149 177 WriteMemberName(name);
150 178
151 179 m_contextStack.Push(m_context);
152 180
153 181 m_context = new Context { element = JSONElementContext.Array, needComma = false };
154 m_writer.Write("[ ");
182 m_writer.Write("[");
155 183 }
156 184
157 185 public void EndArray() {
158 186 if (m_context.element != JSONElementContext.Array)
159 187 OperationNotApplicable("EndArray");
160 188
161 m_writer.Write(" ]");
162 189 m_context = m_contextStack.Pop();
190 WriteIndent();
191 m_writer.Write("]");
163 192 }
164 193
165 194 void Write(bool value) {
166 195 m_writer.Write(value ? "true" : "false");
167 196 }
168 197
169 198
170 199 void Write(string value) {
171 200 if (value == null)
172 201 m_writer.Write("null");
173 202
174 203 var chars = value.ToCharArray();
175 204 m_writer.Write('"');
176 205
177 206 for (int i = 0; i < chars.Length; i++) {
178 207 var ch = chars[i];
179 208
180 209 switch (ch) {
181 210 case '\b':
182 211 m_writer.Write(_escapeBKS);
183 212 break;
184 213 case '\f':
185 214 m_writer.Write(_escapeFWD);
186 215 break;
187 216 case '\r':
188 217 m_writer.Write(_escapeCR);
189 218 break;
190 219 case '\n':
191 220 m_writer.Write(_escapeNL);
192 221 break;
193 222 case '\t':
194 223 m_writer.Write(_escapeTAB);
195 224 break;
196 225 case '\\':
197 226 m_writer.Write(_escapeBSLASH);
198 227 break;
199 228 case '/':
200 229 m_writer.Write(_escapeSLASH);
201 230 break;
202 231 case '"':
203 232 m_writer.Write(_escapeQ);
204 233 break;
205 234 default:
206 235 if (ch < 0x20) {
207 236 m_writer.Write("\\u00{0:x2}",(int)ch);
208 237 } else {
209 238 m_writer.Write(ch);
210 239 }
211 240 break;
212 241 }
213 242 }
214 243
215 244 m_writer.Write('"');
216 245 }
217 246
218 247 void Write(double value) {
219 248 m_writer.Write(value);
220 249 }
221 250
222 251 void OperationNotApplicable(string opName) {
223 252 throw new InvalidOperationException(String.Format("The operation '{0}' isn't applicable in the context of '{1}'", opName, m_context.element ));
224 253 }
225 254
226 255 }
227 256 }
@@ -1,191 +1,194
1 1 using Implab.Diagnostics;
2 2 using System;
3 3 using System.Collections.Generic;
4 4 using System.Diagnostics;
5 5 using System.Linq;
6 6 using System.Text;
7 7 using System.Threading;
8 8
9 9 namespace Implab.Parallels {
10 10 public static class ArrayTraits {
11 11 class ArrayIterator<TSrc> : DispatchPool<int> {
12 12 readonly Action<TSrc> m_action;
13 13 readonly TSrc[] m_source;
14 14 readonly Promise<int> m_promise = new Promise<int>();
15 15 readonly TraceContext m_traceContext;
16 16
17 17 int m_pending;
18 18 int m_next;
19 19
20 20 public ArrayIterator(TSrc[] source, Action<TSrc> action, int threads)
21 21 : base(threads) {
22 22
23 23 Debug.Assert(source != null);
24 24 Debug.Assert(action != null);
25 25
26 26 m_traceContext = TraceContext.Snapshot();
27 27 m_next = 0;
28 28 m_source = source;
29 29 m_pending = source.Length;
30 30 m_action = action;
31 31
32 32 m_promise.Anyway(() => Dispose());
33 33 m_promise.Cancelled(() => Dispose());
34 34
35 35 InitPool();
36 36 }
37 37
38 38 public Promise<int> Promise {
39 39 get {
40 40 return m_promise;
41 41 }
42 42 }
43 43
44 44 protected override void Worker() {
45 45 TraceContext.Fork(m_traceContext);
46 46 base.Worker();
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 ? false : true;
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 TraceContext m_traceContext;
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_traceContext = TraceContext.Snapshot();
88 88
89 89 m_promise.Anyway(() => Dispose());
90 90 m_promise.Cancelled(() => Dispose());
91 91
92 92 InitPool();
93 93 }
94 94
95 95 public Promise<TDst[]> Promise {
96 96 get {
97 97 return m_promise;
98 98 }
99 99 }
100 100
101 101 protected override void Worker() {
102 102 TraceContext.Fork(m_traceContext);
103 103 base.Worker();
104 104 }
105 105
106 106 protected override bool TryDequeue(out int unit) {
107 107 unit = Interlocked.Increment(ref m_next) - 1;
108 108 return unit >= m_source.Length ? false : true;
109 109 }
110 110
111 111 protected override void InvokeUnit(int unit) {
112 112 try {
113 113 m_dest[unit] = m_transform(m_source[unit]);
114 114 var pending = Interlocked.Decrement(ref m_pending);
115 115 if (pending == 0)
116 116 m_promise.Resolve(m_dest);
117 117 } catch (Exception e) {
118 118 m_promise.Reject(e);
119 119 }
120 120 }
121 121 }
122 122
123 123 public static IPromise<TDst[]> ParallelMap<TSrc, TDst> (this TSrc[] source, Func<TSrc,TDst> transform, int threads) {
124 124 if (source == null)
125 125 throw new ArgumentNullException("source");
126 126 if (transform == null)
127 127 throw new ArgumentNullException("transform");
128 128
129 129 var mapper = new ArrayMapper<TSrc, TDst>(source, transform, threads);
130 130 return mapper.Promise;
131 131 }
132 132
133 133 public static IPromise<int> ParallelForEach<TSrc>(this TSrc[] source, Action<TSrc> action, int threads) {
134 134 if (source == null)
135 135 throw new ArgumentNullException("source");
136 136 if (action == null)
137 137 throw new ArgumentNullException("action");
138 138
139 139 var iter = new ArrayIterator<TSrc>(source, action, threads);
140 140 return iter.Promise;
141 141 }
142 142
143 143 public static IPromise<TDst[]> ChainedMap<TSrc, TDst>(this TSrc[] source, ChainedOperation<TSrc, TDst> transform, int threads) {
144 144 if (source == null)
145 145 throw new ArgumentNullException("source");
146 146 if (transform == null)
147 147 throw new ArgumentNullException("transform");
148 148 if (threads <= 0)
149 149 throw new ArgumentOutOfRangeException("Threads number must be greater then zero");
150 150
151 151 if (source.Length == 0)
152 152 return Promise<TDst[]>.ResultToPromise(new TDst[0]);
153 153
154 154 var promise = new Promise<TDst[]>();
155 155 var res = new TDst[source.Length];
156 156 var pending = source.Length;
157 157
158 158 var semaphore = new Semaphore(threads, threads);
159 159
160 160 AsyncPool.InvokeNewThread(() => {
161 161 for (int i = 0; i < source.Length; i++) {
162 162 if(promise.IsResolved)
163 163 break; // stop processing in case of error or cancellation
164 164 var idx = i;
165 165 semaphore.WaitOne();
166 166 try {
167 167 var p1 = transform(source[i]);
168 168 p1.Anyway(() => semaphore.Release());
169 169 p1.Cancelled(() => semaphore.Release());
170 170 p1.Then(
171 171 x => {
172 172 res[idx] = x;
173 173 var left = Interlocked.Decrement(ref pending);
174 174 if (left == 0)
175 175 promise.Resolve(res);
176 176 },
177 e => promise.Reject(e)
177 e => {
178 promise.Reject(e);
179 throw new TransientPromiseException(e);
180 }
178 181 );
179 182
180 183 } catch (Exception e) {
181 184 promise.Reject(e);
182 185 }
183 186 }
184 187 return 0;
185 188 });
186 189
187 190 return promise.Anyway(() => semaphore.Dispose());
188 191 }
189 192
190 193 }
191 194 }
@@ -1,762 +1,731
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.Reflection;
4 4 using System.Diagnostics;
5 5 using System.Threading;
6 6 using Implab.Parallels;
7 7
8 8 namespace Implab {
9 9
10 10 public delegate void ErrorHandler(Exception e);
11 11 public delegate T ErrorHandler<out T>(Exception e);
12 12 public delegate void ResultHandler<in T>(T result);
13 public delegate TNew ResultMapper<in TSrc, out TNew>(TSrc result);
14 public delegate IPromise<TNew> ChainedOperation<in TSrc, TNew>(TSrc result);
13 public delegate TNew ResultMapper<in TSrc,out TNew>(TSrc result);
14 public delegate IPromise<TNew> ChainedOperation<in TSrc,TNew>(TSrc result);
15 15
16 16 /// <summary>
17 17 /// Класс для асинхронного получСния Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ². Π’Π°ΠΊ Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΠΎΠ΅ "ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅".
18 18 /// </summary>
19 19 /// <typeparam name="T">Π’ΠΈΠΏ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌΠΎΠ³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°</typeparam>
20 20 /// <remarks>
21 21 /// <para>БСрвис ΠΏΡ€ΠΈ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ ΠΊ Π΅Π³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρƒ Π΄Π°Π΅Ρ‚ ΠΎΠ±Π΅Ρ‰Π°ΠΈΠ½ΠΈΠ΅ ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ,
22 22 /// ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ² Ρ‚Π°ΠΊΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ряд ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹Ρ… Π²Ρ‹Π·ΠΎΠ²ΠΎ для получСния
23 23 /// событий выполнСния обСщания, Ρ‚ΠΎΠ΅ΡΡ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΈ прСдоставлСнии Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ².</para>
24 24 /// <para>
25 25 /// ΠžΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚Π°ΠΊ ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ с ошибкой. Для подписки Π½Π°
26 26 /// Π΄Π°Π½Π½Ρ‹Π΅ события ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Then</c>.
27 27 /// </para>
28 28 /// <para>
29 29 /// БСрвис, Π² свою ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ, ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ (Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ с ошибкой),
30 30 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Resolve</c> Π»ΠΈΠ±ΠΎ <c>Reject</c> для оповСщСния ΠΊΠ»ΠΈΠ΅Ρ‚Π½Π° ΠΎ
31 31 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ обСщания.
32 32 /// </para>
33 33 /// <para>
34 34 /// Если сСрвСр успСл Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΅Ρ‰Π΅ Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π½Π° Π½Π΅Π³ΠΎ подписался,
35 35 /// Ρ‚ΠΎ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ подписки ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΠ²ΡƒΡŽΡ‰ΠΈΠ΅ события Π² синхронном
36 36 /// Ρ€Π΅ΠΆΠΈΠΌΠ΅ ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΠΎΠ²Π΅Ρ‰Π΅Π½ Π² любом случаС. Π˜Π½Π°Ρ‡Π΅, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ΡΡ Π²
37 37 /// список Π² порядкС подписания ΠΈ Π² этом ΠΆΠ΅ порядкС ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ
38 38 /// обСщания.
39 39 /// </para>
40 40 /// <para>
41 41 /// ΠžΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ обСщания ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Π»ΠΈΠ±ΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ
42 42 /// связанныС асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ‚Π°ΠΊΠΆΠ΅ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ обСщания. Для этого слСдуСт
43 43 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ Ρ„ΠΎΡ€ΠΌΡƒ ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ <c>Then</c>.
44 44 /// </para>
45 45 /// <para>
46 46 /// Π’Π°ΠΊΠΆΠ΅ Ρ…ΠΎΡ€ΠΎΡˆΠΈΠΌ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎΠΌ являСтся Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ <c>Resolve</c> ΠΈ <c>Reject</c> Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ
47 47 /// Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€ обСщания ΠΈΠ½Π°Ρ‡Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ΡŒ противорСчия.
48 48 /// </para>
49 49 /// </remarks>
50 50 public class Promise<T> : IPromise<T> {
51 51
52 52 protected struct HandlerDescriptor {
53 53 public ResultHandler<T> resultHandler;
54 public ErrorHandler errorHandler;
54 public ErrorHandler<T> errorHandler;
55 55 public Action cancellHandler;
56 public Promise<T> medium;
56 57
57 58 public void Resolve(T result) {
58 if (resultHandler != null)
59 if (resultHandler != null) {
59 60 try {
60 61 resultHandler(result);
61 62 } catch (Exception e) {
62 63 Reject(e);
64 return;
63 65 }
66 }
67 if (medium != null)
68 medium.Resolve(result);
64 69 }
65 70
66 71 public void Reject(Exception err) {
67 if (errorHandler != null)
72 if (errorHandler != null) {
68 73 try {
69 errorHandler(err);
70 } catch {
74 var res = errorHandler(err);
75 if (medium != null)
76 medium.Resolve(res);
77 } catch (TransientPromiseException err2) {
78 if (medium != null)
79 medium.Reject(err2.InnerException);
80 } catch (Exception err2) {
81 if (medium != null)
82 medium.Reject(err2);
71 83 }
84 } else if (medium != null)
85 medium.Reject(err);
72 86 }
73 87
74 88 public void Cancel() {
75 if (cancellHandler != null)
89 if (cancellHandler != null) {
76 90 try {
77 91 cancellHandler();
78 } catch {
92 } catch (Exception err) {
93 Reject(err);
94 return;
79 95 }
96 }
97 if (medium != null)
98 medium.Cancel();
80 99 }
81 100 }
82 101
83 102 const int UNRESOLVED_SATE = 0;
84 103 const int TRANSITIONAL_STATE = 1;
85 104 const int SUCCEEDED_STATE = 2;
86 105 const int REJECTED_STATE = 3;
87 106 const int CANCELLED_STATE = 4;
88 107
89 108 readonly bool m_cancellable;
90 109
91 110 int m_childrenCount = 0;
92 111 int m_state;
93 112 T m_result;
94 113 Exception m_error;
95 114
96 115 readonly MTQueue<HandlerDescriptor> m_handlers = new MTQueue<HandlerDescriptor>();
97 116
98 117 public Promise() {
99 118 m_cancellable = true;
100 119 }
101 120
102 121 public Promise(IPromise parent, bool cancellable) {
103 122 m_cancellable = cancellable;
104 123 if (parent != null)
105 AddHandler(
106 null,
107 null,
108 () => {
109 if (parent.IsExclusive)
110 parent.Cancel();
111 }
112 );
124 Cancelled(() => {
125 if (parent.IsExclusive)
126 parent.Cancel();
127 });
113 128 }
114 129
115 130 bool BeginTransit() {
116 131 return UNRESOLVED_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, UNRESOLVED_SATE);
117 132 }
118 133
119 134 void CompleteTransit(int state) {
120 135 if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, state, TRANSITIONAL_STATE))
121 136 throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state");
122 137 }
123 138
124 139 void WaitTransition() {
125 140 while (m_state == TRANSITIONAL_STATE) {
126 141 /* noop */
127 142 }
128 143 }
129 144
130 145 public bool IsResolved {
131 146 get {
132 147 return m_state > 1;
133 148 }
134 149 }
135 150
136 151 public bool IsCancelled {
137 152 get {
138 153 return m_state == CANCELLED_STATE;
139 154 }
140 155 }
141 156
142 157 public Type PromiseType {
143 158 get { return typeof(T); }
144 159 }
145 160
146 161 /// <summary>
147 162 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ.
148 163 /// </summary>
149 164 /// <param name="result">Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния.</param>
150 165 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
151 166 public void Resolve(T result) {
152 167 if (BeginTransit()) {
153 168 m_result = result;
154 169 CompleteTransit(SUCCEEDED_STATE);
155 170 OnStateChanged();
156 171 } else {
157 172 WaitTransition();
158 173 if (m_state != CANCELLED_STATE)
159 174 throw new InvalidOperationException("The promise is already resolved");
160 175 }
161 176 }
162 177
163 178 /// <summary>
164 179 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ. Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ выполнСния Π±ΡƒΠ΄Π΅Ρ‚ пустоС значСния.
165 180 /// </summary>
166 181 /// <remarks>
167 182 /// Π”Π°Π½Π½Ρ‹ΠΉ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ ΡƒΠ΄ΠΎΠ±Π΅Π½ Π² случаях, ΠΊΠΎΠ³Π΄Π° интСрСсСн Ρ„Π°ΠΊΡ‚ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, Π½Π΅ΠΆΠ΅Π»ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.
168 183 /// </remarks>
169 184 public void Resolve() {
170 185 Resolve(default(T));
171 186 }
172 187
173 188 /// <summary>
174 189 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ошибкС
175 190 /// </summary>
176 191 /// <remarks>
177 192 /// ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС, ΠΏΡ€ΠΈ Π΅Π³ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ сразу нСсколько ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²
178 193 /// ΠΌΠΎΠ³Ρƒ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ, ΠΏΡ€ΠΈ этом Ρ‚ΠΎΠ»ΡŒΠΊΠΎ пСрвая Π±ΡƒΠ΄Π΅Ρ‚ использована Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅
179 194 /// Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΡ€ΠΎΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹.
180 195 /// </remarks>
181 196 /// <param name="error">Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ</param>
182 197 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
183 198 public void Reject(Exception error) {
184 199 if (BeginTransit()) {
185 200 m_error = error;
186 201 CompleteTransit(REJECTED_STATE);
187 202 OnStateChanged();
188 203 } else {
189 204 WaitTransition();
190 205 if (m_state == SUCCEEDED_STATE)
191 206 throw new InvalidOperationException("The promise is already resolved");
192 207 }
193 208 }
194 209
195 210 /// <summary>
196 211 /// ΠžΡ‚ΠΌΠ΅Π½ΡΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.
197 212 /// </summary>
198 213 /// <returns><c>true</c> ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΡ Π±Ρ‹Π»Π° ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Π°, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π½Π΅ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹.<c>false</c> ΠΎΡ‚ΠΌΠ΅Π½Π° Π½Π΅ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π°, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ ΠΎΡ‚Ρ€Π°Π±ΠΎΡ‚Π°Π»ΠΈ.</returns>
199 214 public bool Cancel() {
200 if (BeginTransit()) {
215 if (m_cancellable && BeginTransit()) {
201 216 CompleteTransit(CANCELLED_STATE);
202 217 OnStateChanged();
203 218 return true;
204 } else {
205 return false;
206 219 }
220 return false;
207 221 }
208 222
209 223 // сдСлано для Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ° void
210 224 protected void InternalCancel() {
211 225 Cancel();
212 226 }
213 227
214 228 /// <summary>
215 229 /// Adds new handlers to this promise.
216 230 /// </summary>
217 231 /// <param name="success">The handler of the successfully completed operation.
218 232 /// This handler will recieve an operation result as a parameter.</param>
219 /// <param name="error">Handles an exception that may occur during the operation.</param>
220 /// <returns>The new promise chained to this one.</returns>
221 public IPromise<T> Then(ResultHandler<T> success, ErrorHandler error) {
222 if (success == null && error == null)
223 return this;
224
225 var medium = new Promise<T>(this, true);
226
227 ResultHandler<T> resultHandler;
228 if (success != null)
229 resultHandler = x => {
230 success(x);
231 medium.Resolve(x);
232 };
233 else
234 resultHandler = medium.Resolve;
235
236 ErrorHandler errorHandler;
237 if (error != null)
238 errorHandler = x => {
239 // нСсмотря Π½Π° Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки вызываСтся бСзопасно,
240 // Ρ‚.Π΅. возникшиС Π² Π½Π΅ΠΌ ошибки Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠΎΠ΄Π°Π²Π»Π΅Π½Ρ‹, Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ
241 // Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ ошибка Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π° дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ
242 try {
243 error(x);
244 } catch { }
245 medium.Reject(x);
246 };
247 else
248 errorHandler = medium.Reject;
249
250 AddHandler(resultHandler, errorHandler, medium.InternalCancel);
251
252 return medium;
253 }
254
255 public IPromise Then(Action success, ErrorHandler error) {
256 return Then(x => success(), error);
257 }
258
259 public IPromise Then(Action success) {
260 return Then(x => success());
261 }
262
263 /// <summary>
264 /// Adds new handlers to this promise.
265 /// </summary>
266 /// <param name="success">The handler of the successfully completed operation.
267 /// This handler will recieve an operation result as a parameter.</param>
268 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>
269 234 /// <returns>The new promise chained to this one.</returns>
270 235 public IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error) {
271 236 if (success == null && error == null)
272 237 return this;
273 238
274 239 var medium = new Promise<T>(this, true);
275 240
276 ResultHandler<T> resultHandler;
277 ErrorHandler errorHandler;
278
279 if (success != null)
280 resultHandler = x => {
281 success(x);
282 medium.Resolve(x);
283 };
284 else
285 resultHandler = medium.Resolve;
286
287 if (error != null)
288 errorHandler = x => {
289 try {
290 medium.Resolve(error(x));
291 } catch (Exception e) {
292 medium.Reject(e);
293 }
294 };
295 else
296 errorHandler = medium.Reject;
297
298 AddHandler(resultHandler, errorHandler, medium.InternalCancel);
241 AddHandler(success, error, null, medium);
299 242
300 243 return medium;
301 244 }
302 245
246 public IPromise Then(Action success, ErrorHandler error) {
247 return Then(
248 x => success(),
249 e => {
250 error(e);
251 return default(T);
252 }
253 );
254 }
255
256 public IPromise Then(Action success) {
257 return Then(x => success());
258 }
259
303 260
304 261 public IPromise<T> Then(ResultHandler<T> success) {
305 262 if (success == null)
306 263 return this;
307 264
308 265 var medium = new Promise<T>(this, true);
309 266
310 ResultHandler<T> resultHandler;
311
312 if (success != null)
313 resultHandler = x => {
314 success(x);
315 medium.Resolve(x);
316 };
317 else
318 resultHandler = medium.Resolve;
319
320 AddHandler(resultHandler, medium.Reject, medium.InternalCancel);
267 AddHandler(success, null, null, medium);
321 268
322 269 return medium;
323 270 }
324 271
325 public IPromise<T> Error(ErrorHandler error) {
326 return Then((ResultHandler<T>)null, error);
272 public IPromise Error(ErrorHandler error) {
273 if (error == null)
274 return this;
275
276 var medium = new Promise<T>(this, true);
277
278 AddHandler(
279 null,
280 e => {
281 error(e);
282 return default(T);
283 },
284 null,
285 medium
286 );
287
288 return medium;
327 289 }
328 290
329 291 /// <summary>
330 292 /// Handles error and allows to keep the promise.
331 293 /// </summary>
332 294 /// <remarks>
333 295 /// If the specified handler throws an exception, this exception will be used to reject the promise.
334 296 /// </remarks>
335 297 /// <param name="handler">The error handler which returns the result of the promise.</param>
336 298 /// <returns>New promise.</returns>
337 299 public IPromise<T> Error(ErrorHandler<T> handler) {
338 300 if (handler == null)
339 301 return this;
340 302
341 303 var medium = new Promise<T>(this, true);
342 304
343 AddHandler(
344 x => medium.Resolve(x),
345 e => {
346 try {
347 medium.Resolve(handler(e));
348 } catch (Exception e2) {
349 medium.Reject(e2);
350 }
351 },
352 medium.InternalCancel
353 );
305 AddHandler(null, handler, null, medium);
354 306
355 307 return medium;
356 308 }
357 309
358 310 public IPromise<T> Anyway(Action handler) {
359 311 if (handler == null)
360 312 return this;
361 313
362 var medium = new Promise<T>(this,true);
314 var medium = new Promise<T>(this, true);
363 315
364 316 AddHandler(
365 x => {
366 // to avoid handler being called multiple times we handle exception by ourselfs
367 try {
368 handler();
369 medium.Resolve(x);
370 } catch (Exception e) {
371 medium.Reject(e);
372 }
317 x => handler(),
318 e => {
319 handler();
320 throw new TransientPromiseException(e);
373 321 },
374
375 e => {
376 try {
377 handler();
378 } catch { }
379 medium.Reject(e);
380 },
381
382 medium.InternalCancel
322 null,
323 medium
383 324 );
384 325
385 326 return medium;
386 327 }
387 328
388 329 /// <summary>
389 330 /// ΠŸΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ‚ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.
390 331 /// </summary>
391 332 /// <typeparam name="TNew">Новый Ρ‚ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°.</typeparam>
392 333 /// <param name="mapper">ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.</param>
393 334 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
394 335 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
395 336 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ исходного обСщания.</returns>
396 public IPromise<TNew> Map<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler error) {
337 public IPromise<TNew> Map<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler<T> error) {
397 338 if (mapper == null)
398 339 throw new ArgumentNullException("mapper");
399 340
400 341 // создаСм ΠΏΡ€ΠΈΡ†Π΅ΠΏΠ»Π΅Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
401 var chained = new Promise<TNew>(this,true);
342 var chained = new Promise<TNew>(this, true);
402 343
403 344 ResultHandler<T> resultHandler = result => chained.Resolve(mapper(result));
404 ErrorHandler errorHandler = delegate(Exception e) {
405 if (error != null)
345 ErrorHandler<T> errorHandler;
346 if (error != null)
347 errorHandler = e => {
406 348 try {
407 error(e);
408 } catch { }
409 // Π² случаС ошибки Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅
410 chained.Reject(e);
411 };
349 return error(e);
350 } catch (Exception e2) {
351 // Π² случаС ошибки Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅
352 chained.Reject(e2);
353 }
354 return default(T);
355 };
356 else
357 errorHandler = e => {
358 chained.Reject(e);
359 return default(T);
360 };
412 361
413 362
414 363 AddHandler(
415 364 resultHandler,
416 365 errorHandler,
417 chained.InternalCancel
366 chained.InternalCancel,
367 null
418 368 );
419 369
420 370 return chained;
421 371 }
422 372
423 373 public IPromise<TNew> Map<TNew>(ResultMapper<T, TNew> mapper) {
424 374 return Map(mapper, null);
425 375 }
426 376
427 377 /// <summary>
428 378 /// БцСпляСт нСсколько аснхронных ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ. Указанная асинхронная опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½Π° послС
429 379 /// выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ, Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ использован для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ
430 380 /// Π½ΠΎΠ²ΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.
431 381 /// </summary>
432 382 /// <typeparam name="TNew">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</typeparam>
433 383 /// <param name="chained">Асинхронная опСрация, которая Π΄ΠΎΠ»ΠΆΠ½Π° Π±ΡƒΠ΄Π΅Ρ‚ Π½Π°Ρ‡Π°Ρ‚ΡŒΡΡ послС выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ.</param>
434 384 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
435 385 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Ρ‚Π΅ΠΊΡƒΠ΅Ρ‰ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
436 386 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ аснхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</returns>
437 public IPromise<TNew> Chain<TNew>(ChainedOperation<T, TNew> chained, ErrorHandler error) {
387 public IPromise<TNew> Chain<TNew>(ChainedOperation<T, TNew> chained, ErrorHandler<T> error) {
438 388
439 389 // ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ‚ связывания Π΅Ρ‰Π΅ Π½Π΅ Π½Π°Ρ‡Π°Ρ‚Π° асинхронная опСрация, поэтому Π½ΡƒΠΆΠ½ΠΎ
440 390 // ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ посрСдника, ΠΊ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠΎΠ΄Π²Ρ‹Π·ΡΠ²Π°Ρ‚ΡŒΡΡ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ.
441 391 // ΠΊΠΎΠ³Π΄Π° Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° Ρ€Π΅Π°Π»ΡŒΠ½Π°Ρ асинхронная опСрация, ΠΎΠ½Π° ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ ΠΊ посрСднику, Ρ‡Ρ‚ΠΎΠ±Ρ‹
442 392 // ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· Π½Π΅Π³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Ρ€Π°Π±ΠΎΡ‚Ρ‹.
443 393 var medium = new Promise<TNew>(this, true);
444 394
445 395 ResultHandler<T> resultHandler = delegate(T result) {
446 396 if (medium.IsCancelled)
447 397 return;
448 398
449 399 var promise = chained(result);
450 400
451 401 promise.Then(
452 x => medium.Resolve(x),
453 e => medium.Reject(e)
402 medium.Resolve,
403 err => {
404 medium.Reject(err);
405 throw new TransientPromiseException(err);
406 }
454 407 );
455 408
456 409 // notify chained operation that it's not needed anymore
457 410 // порядок Π²Ρ‹Π·ΠΎΠ²Π° Then, Cancelled Π²Π°ΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΡ‚ этого
458 411 // зависит IsExclusive
459 412 medium.Cancelled(() => {
460 if(promise.IsExclusive)
413 if (promise.IsExclusive)
461 414 promise.Cancel();
462 415 });
463 416
464 417 // внСшняя ΠΎΡ‚ΠΌΠ΅Π½Π° связанной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ рассматриваСтся ΠΊΠ°ΠΊ ошибка
465 418 promise.Cancelled(() => medium.Reject(new OperationCanceledException()));
466 419 };
467 420
468 ErrorHandler errorHandler = delegate(Exception e) {
469 if (error != null)
470 error(e);
421 ErrorHandler<T> errorHandler = delegate(Exception e) {
422 if (error != null) {
423 try {
424 return error(e);
425 } catch (Exception e2) {
426 medium.Reject(e2);
427 return default(T);
428 }
429 }
471 430 // Π² случаС ошибки Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅
472 431 medium.Reject(e);
432 return default(T);
473 433 };
474 434
475 435 AddHandler(
476 436 resultHandler,
477 437 errorHandler,
478 medium.InternalCancel
438 medium.InternalCancel,
439 null
479 440 );
480 441
481 442 return medium;
482 443 }
483 444
484 445 public IPromise<TNew> Chain<TNew>(ChainedOperation<T, TNew> chained) {
485 446 return Chain(chained, null);
486 447 }
487 448
488 449 public IPromise<T> Cancelled(Action handler) {
489 AddHandler(null, null, handler);
450 AddHandler(null, null, handler, null);
490 451 return this;
491 452 }
492 453
493 454 /// <summary>
494 455 /// Adds the specified handler for all cases (success, error, cancel)
495 456 /// </summary>
496 457 /// <param name="handler">The handler that will be called anyway</param>
497 458 /// <returns>self</returns>
498 459 public IPromise<T> Finally(Action handler) {
499 460 if (handler == null)
500 461 throw new ArgumentNullException("handler");
501 462 AddHandler(
502 463 x => handler(),
503 e => handler(),
504 handler
464 e => {
465 handler();
466 throw new TransientPromiseException(e);
467 },
468 handler,
469 null
505 470 );
506 471 return this;
507 472 }
508 473
509 474 /// <summary>
510 475 /// ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ обСщания ΠΊ Π½ΡƒΠΆΠ½ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ
511 476 /// </summary>
512 477 /// <typeparam name="T2"></typeparam>
513 478 /// <returns></returns>
514 479 public IPromise<T2> Cast<T2>() {
515 480 return Map(x => (T2)(object)x, null);
516 481 }
517 482
518 483 /// <summary>
519 484 /// ДоТидаСтся ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ³ΠΎ обСщания ΠΈ Π² случаС успСха, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚
520 485 /// Π΅Π³ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС бросаСт ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.
521 486 /// </summary>
522 487 /// <remarks>
523 488 /// <para>
524 489 /// Если ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ обСщания Π±Ρ‹Π»ΠΎ ΠΏΡ€Π΅Ρ€Π²Π°Π½ΠΎ ΠΏΠΎ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚Ρƒ, это Π½Π΅ Π·Π½Π°Ρ‡ΠΈΡ‚,
525 490 /// Ρ‡Ρ‚ΠΎ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±Ρ‹Π»ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½ΠΎ ΠΈΠ»ΠΈ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π² этом Ρ€ΠΎΠ΄Π΅, это Ρ‚ΠΎΠ»ΡŒΠΊΠΎ
526 491 /// ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π΅Π³ΠΎ Π½Π΅ доТдались, ΠΎΠ΄Π½Π°ΠΊΠΎ всС зарСгистрированныС
527 492 /// ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, ΠΊΠ°ΠΊ Π±Ρ‹Π»ΠΈ Ρ‚Π°ΠΊ ΠΎΡΡ‚Π°Π»ΠΈΡΡŒ ΠΈ ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹, ΠΊΠΎΠ³Π΄Π°
528 493 /// ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
529 494 /// </para>
530 495 /// <para>
531 496 /// Π’Π°ΠΊΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π²ΠΏΠΎΠ»Π½Π΅ ΠΎΠΏΡ€Π°Π²Π΄Π°Π½ΠΎ ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΡ‚Π΅Ρ‡ΡŒ
532 497 /// Π² Ρ‚ΠΎΡ‚ ΠΌΠΎΠΌΠ΅Π½Ρ‚, ΠΊΠΎΠ³Π΄Π° Π½Π°Ρ‡Π°Π»Π°ΡΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ², ΠΈ
533 498 /// ΠΊ Ρ‚ΠΎΠΌΡƒ ΠΆΠ΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡ‚ΠΎΡΡ‚ΡŒ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ ΠΈ Π΅Π³ΠΎ
534 499 /// ΠΎΡ‚ΠΊΠ»ΠΎΠ½Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ Π½Π΅ΠΏΡ€ΠΎΠ³Π½ΠΎΠ·ΠΈΡ€ΡƒΠ΅ΠΌΠΎΠΌΡƒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρƒ.
535 500 /// </para>
536 501 /// </remarks>
537 502 /// <param name="timeout">ВрСмя оТидания</param>
538 503 /// <returns>Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния обСщания</returns>
539 504 public T Join(int timeout) {
540 505 var evt = new ManualResetEvent(false);
541 506 Anyway(() => evt.Set());
542 507 Cancelled(() => evt.Set());
543 508
544 509 if (!evt.WaitOne(timeout, true))
545 510 throw new TimeoutException();
546 511
547 512 switch (m_state) {
548 513 case SUCCEEDED_STATE:
549 514 return m_result;
550 515 case CANCELLED_STATE:
551 516 throw new OperationCanceledException();
552 517 case REJECTED_STATE:
553 518 throw new TargetInvocationException(m_error);
554 519 default:
555 520 throw new ApplicationException(String.Format("Invalid promise state {0}", m_state));
556 521 }
557 522 }
558 523
559 524 public T Join() {
560 525 return Join(Timeout.Infinite);
561 526 }
562 527
563 void AddHandler(ResultHandler<T> success, ErrorHandler error, Action cancel) {
528 void AddHandler(ResultHandler<T> success, ErrorHandler<T> error, Action cancel, Promise<T> medium) {
564 529 if (success != null || error != null)
565 530 Interlocked.Increment(ref m_childrenCount);
566 531
567 HandlerDescriptor handler = new HandlerDescriptor {
532 var handler = new HandlerDescriptor {
568 533 resultHandler = success,
569 534 errorHandler = error,
570 cancellHandler = cancel
535 cancellHandler = cancel,
536 medium = medium
571 537 };
572 538
573 539 bool queued;
574 540
575 541 if (!IsResolved) {
576 542 m_handlers.Enqueue(handler);
577 543 queued = true;
578 544 } else {
579 545 // the promise is in resolved state, just invoke the handled with minimum overhead
580 546 queued = false;
581 547 InvokeHandler(handler);
582 548 }
583 549
584 550 if (queued && IsResolved && m_handlers.TryDequeue(out handler))
585 551 // if the promise have been resolved while we was adding handler to the queue
586 552 // we can't guarantee that someone is still processing it
587 553 // therefore we will fetch a handler from the queue and execute it
588 554 // note that fetched handler may be not the one that we have added
589 555 // even we can fetch no handlers at all :)
590 556 InvokeHandler(handler);
591 557 }
592 558
593 559 protected virtual void InvokeHandler(HandlerDescriptor handler) {
594 560 switch (m_state) {
595 561 case SUCCEEDED_STATE:
596 562 handler.Resolve(m_result);
597 563 break;
598 564 case REJECTED_STATE:
599 565 handler.Reject(m_error);
600 566 break;
601 567 case CANCELLED_STATE:
602 568 handler.Cancel();
603 569 break;
604 570 default:
605 571 // do nothing
606 572 return;
607 573 }
608 574 }
609 575
610 576 void OnStateChanged() {
611 577 HandlerDescriptor handler;
612 578 while (m_handlers.TryDequeue(out handler))
613 579 InvokeHandler(handler);
614 580 }
615 581
616 582 public bool IsExclusive {
617 583 get {
618 584 return m_childrenCount <= 1;
619 585 }
620 586 }
621 587
622 588 /// <summary>
623 589 /// ΠžΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ нСсколько ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ являСтся массив Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
624 590 /// Если хотябы ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚ΠΎ Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ Ρ‚ΠΎΠΆΠ΅ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
625 591 /// ΠŸΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ Π½ΠΎΠ²ΠΎΠ³ΠΎ обСщания, ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅ обСщания Ρ‚Π°ΠΊΠΆΠ΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Ρ‹, Ссли Π½ΠΈΠΊΡ‚ΠΎ большС Π½Π° Π½ΠΈΡ… Π½Π΅ подписан.
626 592 /// </summary>
627 593 /// <param name="promises">Бписок ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ. Если список пустой, Ρ‚ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ возвращаСтся ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹ΠΌ.</param>
628 594 /// <returns>ΠžΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰Π΅Π΅ Π² сСбС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.</returns>
629 595 /// <exception cref="ArgumentNullException"><paramref name="promises"/> Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ null</exception>
630 596 public static IPromise<T[]> CreateComposite(IList<IPromise<T>> promises) {
631 597 if (promises == null)
632 598 throw new ArgumentNullException();
633 599
634 600 // создаСм аккумулятор для Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² ΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
635 601 var result = new T[promises.Count];
636 602 var promise = new Promise<T[]>();
637 603
638 604 // special case
639 605 if (promises.Count == 0) {
640 606 promise.Resolve(result);
641 607 return promise;
642 608 }
643 609
644 610 int pending = promises.Count;
645 611
646 612 for (int i = 0; i < promises.Count; i++) {
647 613 var dest = i;
648 614
649 615 if (promises[i] != null) {
650 616 promises[i].Then(
651 617 x => {
652 618 result[dest] = x;
653 619 if (Interlocked.Decrement(ref pending) == 0)
654 620 promise.Resolve(result);
655 621 },
656 e => promise.Reject(e)
622 e => {
623 promise.Reject(e);
624 return default(T);
625 }
657 626 );
658 627 } else {
659 628 if (Interlocked.Decrement(ref pending) == 0)
660 629 promise.Resolve(result);
661 630 }
662 631 }
663 632
664 633 promise.Cancelled(
665 634 () => {
666 635 foreach (var d in promises)
667 636 if (d != null && d.IsExclusive)
668 637 d.Cancel();
669 638 }
670 639 );
671 640
672 641 return promise;
673 642 }
674 643
675 644 /// <summary>
676 645 /// ΠžΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ нСсколько ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎ. Π Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ
677 646 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ всСх ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ. ΠŸΡ€ΠΈ этом Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹Π΅ значСния ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ
678 647 /// ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΡƒΡŽΡ‚ΡΡ.
679 648 /// </summary>
680 649 /// <param name="promises">ΠšΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΡ ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹Ρ… ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΠ±ΡŠΠ΅Π΄Π΅Π½Π΅Π½Ρ‹ Π² ΠΎΠ΄Π½ΠΎ.</param>
681 650 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰Π΅Π΅ Π² сСбС ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅.</returns>
682 651 /// <remarks>
683 652 /// Если Π² ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΈ Π²ΡΡ‚Ρ€Π΅Ρ‡Π°ΡŽΡŒΡΡ <c>null</c>, Ρ‚ΠΎ ΠΎΠ½ΠΈ Π²ΠΎΡΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹Π΅ обСщания.
684 653 /// </remarks>
685 654 public static IPromise CreateComposite(ICollection<IPromise> promises) {
686 655 if (promises == null)
687 656 throw new ArgumentNullException();
688 657 if (promises.Count == 0)
689 658 return Promise<object>.ResultToPromise(null);
690 659
691 660 int countdown = promises.Count;
692 661
693 662 var result = new Promise<object>();
694 663
695 664 foreach (var d in promises) {
696 665 if (d == null) {
697 666 if (Interlocked.Decrement(ref countdown) == 0)
698 667 result.Resolve(null);
699 668 } else {
700 669 d.Then(() => {
701 670 if (Interlocked.Decrement(ref countdown) == 0)
702 671 result.Resolve(null);
703 672 });
704 673 }
705 674 }
706 675
707 676 result.Cancelled(() => {
708 677 foreach (var d in promises)
709 678 if (d != null && d.IsExclusive)
710 679 d.Cancel();
711 680 });
712 681
713 682 return result;
714 683 }
715 684
716 685 public static Promise<T> ResultToPromise(T result) {
717 686 var p = new Promise<T>();
718 687 p.Resolve(result);
719 688 return p;
720 689 }
721 690
722 691 public static Promise<T> ExceptionToPromise(Exception error) {
723 692 if (error == null)
724 693 throw new ArgumentNullException();
725 694
726 695 var p = new Promise<T>();
727 696 p.Reject(error);
728 697 return p;
729 698 }
730 699
731 700 #region IPromiseBase explicit implementation
732 701
733 702 IPromise IPromise.Error(ErrorHandler error) {
734 703 return Error(error);
735 704 }
736 705
737 706 IPromise IPromise.Anyway(Action handler) {
738 707 return Anyway(handler);
739 708 }
740 709
741 710 IPromise IPromise.Finally(Action handler) {
742 711 return Finally(handler);
743 712 }
744 713
745 714 IPromise IPromise.Cancelled(Action handler) {
746 715 return Cancelled(handler);
747 716 }
748 717
749 718 void IPromise.Join() {
750 719 Join();
751 720 }
752 721
753 722 void IPromise.Join(int timeout) {
754 723 Join(timeout);
755 724 }
756 725
757 726 #endregion
758 727
759 728
760 729
761 730 }
762 731 }
General Comments 0
You need to be logged in to leave comments. Login now