@@ -31,6 +31,23 | |||||
31 | <ErrorReport>prompt</ErrorReport> |
|
31 | <ErrorReport>prompt</ErrorReport> | |
32 | <WarningLevel>4</WarningLevel> |
|
32 | <WarningLevel>4</WarningLevel> | |
33 | </PropertyGroup> |
|
33 | </PropertyGroup> | |
|
34 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' "> | |||
|
35 | <DebugSymbols>true</DebugSymbols> | |||
|
36 | <DebugType>full</DebugType> | |||
|
37 | <Optimize>false</Optimize> | |||
|
38 | <OutputPath>bin\Debug\</OutputPath> | |||
|
39 | <DefineConstants>DEBUG;TRACE</DefineConstants> | |||
|
40 | <ErrorReport>prompt</ErrorReport> | |||
|
41 | <WarningLevel>4</WarningLevel> | |||
|
42 | </PropertyGroup> | |||
|
43 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' "> | |||
|
44 | <DebugType>pdbonly</DebugType> | |||
|
45 | <Optimize>true</Optimize> | |||
|
46 | <OutputPath>bin\Release\</OutputPath> | |||
|
47 | <DefineConstants>TRACE</DefineConstants> | |||
|
48 | <ErrorReport>prompt</ErrorReport> | |||
|
49 | <WarningLevel>4</WarningLevel> | |||
|
50 | </PropertyGroup> | |||
34 | <ItemGroup> |
|
51 | <ItemGroup> | |
35 | <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" /> |
|
52 | <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" /> | |
36 | <Reference Include="System" /> |
|
53 | <Reference Include="System" /> |
@@ -30,6 +30,23 | |||||
30 | <ErrorReport>prompt</ErrorReport> |
|
30 | <ErrorReport>prompt</ErrorReport> | |
31 | <WarningLevel>4</WarningLevel> |
|
31 | <WarningLevel>4</WarningLevel> | |
32 | </PropertyGroup> |
|
32 | </PropertyGroup> | |
|
33 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' "> | |||
|
34 | <DebugSymbols>true</DebugSymbols> | |||
|
35 | <DebugType>full</DebugType> | |||
|
36 | <Optimize>false</Optimize> | |||
|
37 | <OutputPath>bin\Debug\</OutputPath> | |||
|
38 | <DefineConstants>DEBUG;TRACE</DefineConstants> | |||
|
39 | <ErrorReport>prompt</ErrorReport> | |||
|
40 | <WarningLevel>4</WarningLevel> | |||
|
41 | </PropertyGroup> | |||
|
42 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' "> | |||
|
43 | <DebugType>pdbonly</DebugType> | |||
|
44 | <Optimize>true</Optimize> | |||
|
45 | <OutputPath>bin\Release\</OutputPath> | |||
|
46 | <DefineConstants>TRACE</DefineConstants> | |||
|
47 | <ErrorReport>prompt</ErrorReport> | |||
|
48 | <WarningLevel>4</WarningLevel> | |||
|
49 | </PropertyGroup> | |||
33 | <ItemGroup> |
|
50 | <ItemGroup> | |
34 | <Reference Include="System" /> |
|
51 | <Reference Include="System" /> | |
35 | <Reference Include="System.Core" /> |
|
52 | <Reference Include="System.Core" /> |
@@ -31,6 +31,23 | |||||
31 | <ErrorReport>prompt</ErrorReport> |
|
31 | <ErrorReport>prompt</ErrorReport> | |
32 | <WarningLevel>4</WarningLevel> |
|
32 | <WarningLevel>4</WarningLevel> | |
33 | </PropertyGroup> |
|
33 | </PropertyGroup> | |
|
34 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' "> | |||
|
35 | <DebugSymbols>true</DebugSymbols> | |||
|
36 | <DebugType>full</DebugType> | |||
|
37 | <Optimize>false</Optimize> | |||
|
38 | <OutputPath>bin\Debug\</OutputPath> | |||
|
39 | <DefineConstants>DEBUG;TRACE</DefineConstants> | |||
|
40 | <ErrorReport>prompt</ErrorReport> | |||
|
41 | <WarningLevel>4</WarningLevel> | |||
|
42 | </PropertyGroup> | |||
|
43 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' "> | |||
|
44 | <DebugType>pdbonly</DebugType> | |||
|
45 | <Optimize>true</Optimize> | |||
|
46 | <OutputPath>bin\Release\</OutputPath> | |||
|
47 | <DefineConstants>TRACE</DefineConstants> | |||
|
48 | <ErrorReport>prompt</ErrorReport> | |||
|
49 | <WarningLevel>4</WarningLevel> | |||
|
50 | </PropertyGroup> | |||
34 | <ItemGroup> |
|
51 | <ItemGroup> | |
35 | <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" /> |
|
52 | <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" /> | |
36 | <Reference Include="System" /> |
|
53 | <Reference Include="System" /> |
@@ -20,22 +20,40 Global | |||||
20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution |
|
20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution | |
21 | Debug|Any CPU = Debug|Any CPU |
|
21 | Debug|Any CPU = Debug|Any CPU | |
22 | Release|Any CPU = Release|Any CPU |
|
22 | Release|Any CPU = Release|Any CPU | |
|
23 | Debug 4.5|Any CPU = Debug 4.5|Any CPU | |||
|
24 | Release 4.5|Any CPU = Release 4.5|Any CPU | |||
23 | EndGlobalSection |
|
25 | EndGlobalSection | |
24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution |
|
26 | GlobalSection(ProjectConfigurationPlatforms) = postSolution | |
|
27 | {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU | |||
|
28 | {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU | |||
25 | {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|
29 | {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |
26 | {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|
30 | {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug|Any CPU.Build.0 = Debug|Any CPU | |
|
31 | {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU | |||
|
32 | {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU | |||
27 | {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|
33 | {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release|Any CPU.ActiveCfg = Release|Any CPU | |
28 | {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release|Any CPU.Build.0 = Release|Any CPU |
|
34 | {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release|Any CPU.Build.0 = Release|Any CPU | |
|
35 | {2F31E405-E267-4195-A05D-574093C21209}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU | |||
|
36 | {2F31E405-E267-4195-A05D-574093C21209}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU | |||
29 | {2F31E405-E267-4195-A05D-574093C21209}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|
37 | {2F31E405-E267-4195-A05D-574093C21209}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |
30 | {2F31E405-E267-4195-A05D-574093C21209}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|
38 | {2F31E405-E267-4195-A05D-574093C21209}.Debug|Any CPU.Build.0 = Debug|Any CPU | |
|
39 | {2F31E405-E267-4195-A05D-574093C21209}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU | |||
|
40 | {2F31E405-E267-4195-A05D-574093C21209}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU | |||
31 | {2F31E405-E267-4195-A05D-574093C21209}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|
41 | {2F31E405-E267-4195-A05D-574093C21209}.Release|Any CPU.ActiveCfg = Release|Any CPU | |
32 | {2F31E405-E267-4195-A05D-574093C21209}.Release|Any CPU.Build.0 = Release|Any CPU |
|
42 | {2F31E405-E267-4195-A05D-574093C21209}.Release|Any CPU.Build.0 = Release|Any CPU | |
|
43 | {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU | |||
|
44 | {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU | |||
33 | {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|
45 | {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 |
|
46 | {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug|Any CPU.Build.0 = Debug|Any CPU | |
|
47 | {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU | |||
|
48 | {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU | |||
35 | {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|
49 | {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 |
|
50 | {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release|Any CPU.Build.0 = Release|Any CPU | |
|
51 | {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU | |||
|
52 | {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU | |||
37 | {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|
53 | {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 |
|
54 | {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug|Any CPU.Build.0 = Debug|Any CPU | |
|
55 | {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU | |||
|
56 | {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU | |||
39 | {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|
57 | {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 |
|
58 | {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release|Any CPU.Build.0 = Release|Any CPU | |
41 | EndGlobalSection |
|
59 | EndGlobalSection |
@@ -27,16 +27,26 namespace Implab { | |||||
27 | /// </summary> |
|
27 | /// </summary> | |
28 | bool IsCancelled { get; } |
|
28 | bool IsCancelled { get; } | |
29 |
|
29 | |||
30 | IPromise Then(Action success,ErrorHandler error); |
|
30 | IPromise Then(Action success, ErrorHandler error, Action cancel); | |
|
31 | IPromise Then(Action success, ErrorHandler error); | |||
31 | IPromise Then(Action success); |
|
32 | IPromise Then(Action success); | |
|
33 | ||||
|
34 | /// <summary> | |||
|
35 | /// ΠΠΎΠ±Π°Π²Π»ΡΠ΅Ρ ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΉ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ Π² ΡΠ΅ΠΏΠΎΡΠΊΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΉ, Π½Π΅ ΡΠΎΠ·Π΄Π°Π΅Ρ ΠΏΡΠΎΠΌΠ΅ΠΆΡΡΠΎΡΠ½ΡΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΉ. | |||
|
36 | /// </summary> | |||
|
37 | /// <param name="success">Success.</param> | |||
|
38 | /// <param name="error">Error.</param> | |||
|
39 | /// <param name="cancel">Cancel.</param> | |||
|
40 | void Last(Action success, ErrorHandler error, Action cancel); | |||
|
41 | void Last(Action success, ErrorHandler error); | |||
|
42 | void Last(Action success); | |||
|
43 | ||||
32 | IPromise Error(ErrorHandler error); |
|
44 | IPromise Error(ErrorHandler error); | |
33 | /// <summary> |
|
45 | /// <summary> | |
34 | /// ΠΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ Π»ΠΈΠ±ΠΎ ΠΎΡΠΈΠ±ΠΊΡ, Π»ΠΈΠ±ΠΎ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ. Π‘ΠΎΠ±ΡΡΠΈΠ΅ ΠΎΡΠΌΠ΅Π½Ρ Π½Π΅ ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π΅ΡΡΡ. |
|
46 | /// ΠΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ Π»ΠΈΠ±ΠΎ ΠΎΡΠΈΠ±ΠΊΡ, Π»ΠΈΠ±ΠΎ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ. Π‘ΠΎΠ±ΡΡΠΈΠ΅ ΠΎΡΠΌΠ΅Π½Ρ Π½Π΅ ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π΅ΡΡΡ. | |
35 | /// </summary> |
|
47 | /// </summary> | |
36 | /// <param name="handler">ΠΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ.</param> |
|
48 | /// <param name="handler">ΠΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ.</param> | |
37 | /// <remarks>ΠΠΎΡΠ»Π΅ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ΅ ΠΎΡΠΈΠ±ΠΊΠΈ, ΠΎΠ½Π° ΠΏΠ΅ΡΠ΅Π΄Π°Π΅ΡΡΡ Π΄Π°Π»ΡΡΠ΅.</remarks> |
|
49 | /// <remarks>ΠΠΎΡΠ»Π΅ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ΅ ΠΎΡΠΈΠ±ΠΊΠΈ, ΠΎΠ½Π° ΠΏΠ΅ΡΠ΅Π΄Π°Π΅ΡΡΡ Π΄Π°Π»ΡΡΠ΅.</remarks> | |
38 | IPromise Anyway(Action handler); |
|
|||
39 |
|
||||
40 | /// <summary> |
|
50 | /// <summary> | |
41 | /// ΠΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ Π»ΠΈΠ±ΠΎ ΠΎΡΠΈΠ±ΠΊΡ, Π»ΠΈΠ±ΠΎ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ, Π»ΠΈΠ±ΠΎ ΠΎΡΠΌΠ΅Π½Ρ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΡ. |
|
51 | /// ΠΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ Π»ΠΈΠ±ΠΎ ΠΎΡΠΈΠ±ΠΊΡ, Π»ΠΈΠ±ΠΎ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ, Π»ΠΈΠ±ΠΎ ΠΎΡΠΌΠ΅Π½Ρ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΡ. | |
42 | /// </summary> |
|
52 | /// </summary> |
@@ -3,27 +3,35 using System.Collections.Generic; | |||||
3 | using System.Linq; |
|
3 | using System.Linq; | |
4 | using System.Text; |
|
4 | using System.Text; | |
5 |
|
5 | |||
6 | namespace Implab |
|
6 | namespace Implab { | |
7 | { |
|
7 | public interface IPromise<T>: IPromise { | |
8 | public interface IPromise<T>: IPromise |
|
|||
9 | { |
|
|||
10 |
|
8 | |||
11 | new T Join(); |
|
9 | new T Join(); | |
|
10 | ||||
12 | new T Join(int timeout); |
|
11 | new T Join(int timeout); | |
13 |
|
12 | |||
|
13 | IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error, Action cancel); | |||
|
14 | ||||
14 | IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error); |
|
15 | IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error); | |
|
16 | ||||
15 | IPromise<T> Then(ResultHandler<T> success); |
|
17 | IPromise<T> Then(ResultHandler<T> success); | |
|
18 | ||||
|
19 | void Last(ResultHandler<T> success, ErrorHandler error, Action cancel); | |||
|
20 | void Last(ResultHandler<T> success, ErrorHandler error); | |||
|
21 | void Last(ResultHandler<T> success); | |||
|
22 | ||||
16 | IPromise<T> Error(ErrorHandler<T> error); |
|
23 | IPromise<T> Error(ErrorHandler<T> error); | |
17 |
|
24 | |||
18 |
IPromise<T2> |
|
25 | IPromise<T2> Then<T2>(ResultMapper<T,T2> mapper, ErrorHandler<T> error); | |
19 | IPromise<T2> Map<T2>(ResultMapper<T, T2> mapper); |
|
26 | ||
|
27 | IPromise<T2> Then<T2>(ResultMapper<T,T2> mapper); | |||
20 |
|
28 | |||
21 |
IPromise<T2> |
|
29 | IPromise<T2> Then<T2>(ChainedOperation<T, T2> chained, ErrorHandler<T> error); | |
22 | IPromise<T2> Chain<T2>(ChainedOperation<T, T2> chained); |
|
30 | ||
|
31 | IPromise<T2> Then<T2>(ChainedOperation<T, T2> chained); | |||
23 |
|
32 | |||
24 | new IPromise<T> Cancelled(Action handler); |
|
33 | new IPromise<T> Cancelled(Action handler); | |
|
34 | ||||
25 | new IPromise<T> Finally(Action handler); |
|
35 | new IPromise<T> Finally(Action handler); | |
26 | new IPromise<T> Anyway(Action handler); |
|
|||
27 |
|
||||
28 | } |
|
36 | } | |
29 | } |
|
37 | } |
@@ -29,6 +29,25 | |||||
29 | <WarningLevel>4</WarningLevel> |
|
29 | <WarningLevel>4</WarningLevel> | |
30 | <ConsolePause>false</ConsolePause> |
|
30 | <ConsolePause>false</ConsolePause> | |
31 | </PropertyGroup> |
|
31 | </PropertyGroup> | |
|
32 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' "> | |||
|
33 | <DebugSymbols>true</DebugSymbols> | |||
|
34 | <DebugType>full</DebugType> | |||
|
35 | <Optimize>false</Optimize> | |||
|
36 | <OutputPath>bin\Debug</OutputPath> | |||
|
37 | <DefineConstants>TRACE;DEBUG;NET_4_5</DefineConstants> | |||
|
38 | <ErrorReport>prompt</ErrorReport> | |||
|
39 | <WarningLevel>4</WarningLevel> | |||
|
40 | <RunCodeAnalysis>true</RunCodeAnalysis> | |||
|
41 | <ConsolePause>false</ConsolePause> | |||
|
42 | </PropertyGroup> | |||
|
43 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' "> | |||
|
44 | <Optimize>true</Optimize> | |||
|
45 | <OutputPath>bin\Release</OutputPath> | |||
|
46 | <ErrorReport>prompt</ErrorReport> | |||
|
47 | <WarningLevel>4</WarningLevel> | |||
|
48 | <ConsolePause>false</ConsolePause> | |||
|
49 | <DefineConstants>NET_4_5</DefineConstants> | |||
|
50 | </PropertyGroup> | |||
32 | <ItemGroup> |
|
51 | <ItemGroup> | |
33 | <Reference Include="System" /> |
|
52 | <Reference Include="System" /> | |
34 | <Reference Include="System.Xml" /> |
|
53 | <Reference Include="System.Xml" /> |
@@ -29,8 +29,7 namespace Implab.Parallels { | |||||
29 | m_pending = source.Length; |
|
29 | m_pending = source.Length; | |
30 | m_action = action; |
|
30 | m_action = action; | |
31 |
|
31 | |||
32 |
m_promise. |
|
32 | m_promise.Finally(Dispose); | |
33 | m_promise.Cancelled(() => Dispose()); |
|
|||
34 |
|
33 | |||
35 | InitPool(); |
|
34 | InitPool(); | |
36 | } |
|
35 | } | |
@@ -48,7 +47,7 namespace Implab.Parallels { | |||||
48 |
|
47 | |||
49 | protected override bool TryDequeue(out int unit) { |
|
48 | protected override bool TryDequeue(out int unit) { | |
50 | unit = Interlocked.Increment(ref m_next) - 1; |
|
49 | unit = Interlocked.Increment(ref m_next) - 1; | |
51 |
return unit |
|
50 | return unit < m_source.Length; | |
52 | } |
|
51 | } | |
53 |
|
52 | |||
54 | protected override void InvokeUnit(int unit) { |
|
53 | protected override void InvokeUnit(int unit) { | |
@@ -86,8 +85,7 namespace Implab.Parallels { | |||||
86 | m_transform = transform; |
|
85 | m_transform = transform; | |
87 | m_traceContext = TraceContext.Snapshot(); |
|
86 | m_traceContext = TraceContext.Snapshot(); | |
88 |
|
87 | |||
89 |
m_promise. |
|
88 | m_promise.Finally(Dispose); | |
90 | m_promise.Cancelled(() => Dispose()); |
|
|||
91 |
|
89 | |||
92 | InitPool(); |
|
90 | InitPool(); | |
93 | } |
|
91 | } | |
@@ -157,16 +155,17 namespace Implab.Parallels { | |||||
157 |
|
155 | |||
158 | var semaphore = new Semaphore(threads, threads); |
|
156 | var semaphore = new Semaphore(threads, threads); | |
159 |
|
157 | |||
|
158 | // Analysis disable AccessToDisposedClosure | |||
160 | AsyncPool.InvokeNewThread(() => { |
|
159 | AsyncPool.InvokeNewThread(() => { | |
161 | for (int i = 0; i < source.Length; i++) { |
|
160 | for (int i = 0; i < source.Length; i++) { | |
162 | if(promise.IsResolved) |
|
161 | if(promise.IsResolved) | |
163 | break; // stop processing in case of error or cancellation |
|
162 | break; // stop processing in case of error or cancellation | |
164 | var idx = i; |
|
163 | var idx = i; | |
|
164 | ||||
165 | semaphore.WaitOne(); |
|
165 | semaphore.WaitOne(); | |
166 | try { |
|
166 | try { | |
167 | var p1 = transform(source[i]); |
|
167 | var p1 = transform(source[i]); | |
168 |
p1. |
|
168 | p1.Finally(() => semaphore.Release()); | |
169 | p1.Cancelled(() => semaphore.Release()); |
|
|||
170 | p1.Then( |
|
169 | p1.Then( | |
171 | x => { |
|
170 | x => { | |
172 | res[idx] = x; |
|
171 | res[idx] = x; | |
@@ -187,7 +186,7 namespace Implab.Parallels { | |||||
187 | return 0; |
|
186 | return 0; | |
188 | }); |
|
187 | }); | |
189 |
|
188 | |||
190 |
return promise. |
|
189 | return promise.Finally(semaphore.Dispose); | |
191 | } |
|
190 | } | |
192 |
|
191 | |||
193 | } |
|
192 | } |
@@ -225,6 +225,18 namespace Implab { | |||||
225 | Cancel(); |
|
225 | Cancel(); | |
226 | } |
|
226 | } | |
227 |
|
227 | |||
|
228 | ||||
|
229 | public IPromise<T> Then(ResultHandler<T> success, ErrorHandler<T> error, Action cancel) { | |||
|
230 | if (success == null && error == null && cancel == null) | |||
|
231 | return this; | |||
|
232 | ||||
|
233 | var medium = new Promise<T>(this, true); | |||
|
234 | ||||
|
235 | AddHandler(success, error, cancel, medium); | |||
|
236 | ||||
|
237 | return medium; | |||
|
238 | } | |||
|
239 | ||||
228 | /// <summary> |
|
240 | /// <summary> | |
229 | /// Adds new handlers to this promise. |
|
241 | /// Adds new handlers to this promise. | |
230 | /// </summary> |
|
242 | /// </summary> | |
@@ -243,6 +255,17 namespace Implab { | |||||
243 | return medium; |
|
255 | return medium; | |
244 | } |
|
256 | } | |
245 |
|
257 | |||
|
258 | public IPromise Then(Action success, ErrorHandler error, Action cancel) { | |||
|
259 | return Then( | |||
|
260 | x => success(), | |||
|
261 | e => { | |||
|
262 | error(e); | |||
|
263 | return default(T); | |||
|
264 | }, | |||
|
265 | cancel | |||
|
266 | ); | |||
|
267 | } | |||
|
268 | ||||
246 | public IPromise Then(Action success, ErrorHandler error) { |
|
269 | public IPromise Then(Action success, ErrorHandler error) { | |
247 | return Then( |
|
270 | return Then( | |
248 | x => success(), |
|
271 | x => success(), | |
@@ -269,6 +292,39 namespace Implab { | |||||
269 | return medium; |
|
292 | return medium; | |
270 | } |
|
293 | } | |
271 |
|
294 | |||
|
295 | public void Last(ResultHandler<T> success, ErrorHandler error, Action cancel) { | |||
|
296 | if (success == null && error == null && cancel == null) | |||
|
297 | return; | |||
|
298 | ||||
|
299 | ErrorHandler<T> errorHandler = null; | |||
|
300 | if (error != null) | |||
|
301 | errorHandler = err => { | |||
|
302 | error(err); | |||
|
303 | return default(T); | |||
|
304 | }; | |||
|
305 | AddHandler(success, errorHandler, cancel, null); | |||
|
306 | } | |||
|
307 | ||||
|
308 | public void Last(ResultHandler<T> success, ErrorHandler error) { | |||
|
309 | Last(success, error, null); | |||
|
310 | } | |||
|
311 | ||||
|
312 | public void Last(ResultHandler<T> success) { | |||
|
313 | Last(success, null, null); | |||
|
314 | } | |||
|
315 | ||||
|
316 | public void Last(Action success,ErrorHandler error, Action cancel) { | |||
|
317 | Last(x => success(), error, cancel); | |||
|
318 | } | |||
|
319 | ||||
|
320 | public void Last(Action success,ErrorHandler error) { | |||
|
321 | Last(x => success(), error, null); | |||
|
322 | } | |||
|
323 | ||||
|
324 | public void Last(Action success) { | |||
|
325 | Last(x => success(), null, null); | |||
|
326 | } | |||
|
327 | ||||
272 | public IPromise Error(ErrorHandler error) { |
|
328 | public IPromise Error(ErrorHandler error) { | |
273 | if (error == null) |
|
329 | if (error == null) | |
274 | return this; |
|
330 | return this; | |
@@ -307,25 +363,6 namespace Implab { | |||||
307 | return medium; |
|
363 | return medium; | |
308 | } |
|
364 | } | |
309 |
|
365 | |||
310 | public IPromise<T> Anyway(Action handler) { |
|
|||
311 | if (handler == null) |
|
|||
312 | return this; |
|
|||
313 |
|
||||
314 | var medium = new Promise<T>(this, true); |
|
|||
315 |
|
||||
316 | AddHandler( |
|
|||
317 | x => handler(), |
|
|||
318 | e => { |
|
|||
319 | handler(); |
|
|||
320 | throw new TransientPromiseException(e); |
|
|||
321 | }, |
|
|||
322 | null, |
|
|||
323 | medium |
|
|||
324 | ); |
|
|||
325 |
|
||||
326 | return medium; |
|
|||
327 | } |
|
|||
328 |
|
||||
329 | /// <summary> |
|
366 | /// <summary> | |
330 | /// ΠΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°ΡΡ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ Π²ΡΠΏΠΎΠ»Π΅Π½ΠΈΡ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ ΠΊ Π½ΠΎΠ²ΠΎΠΌΡ ΡΠΈΠΏΡ. |
|
367 | /// ΠΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°ΡΡ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ Π²ΡΠΏΠΎΠ»Π΅Π½ΠΈΡ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ ΠΊ Π½ΠΎΠ²ΠΎΠΌΡ ΡΠΈΠΏΡ. | |
331 | /// </summary> |
|
368 | /// </summary> | |
@@ -334,7 +371,7 namespace Implab { | |||||
334 | /// <param name="error">ΠΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΠΎΡΠΈΠ±ΠΊΠΈ. ΠΠ°Π½Π½ΡΠΉ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΠΏΠΎΠ»ΡΡΠΈΡ |
|
371 | /// <param name="error">ΠΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΠΎΡΠΈΠ±ΠΊΠΈ. ΠΠ°Π½Π½ΡΠΉ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΠΏΠΎΠ»ΡΡΠΈΡ | |
335 | /// ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π²ΠΎΠ·Π½ΠΈΠΊΡΠ΅Π΅ ΠΏΡΠΈ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ.</param> |
|
372 | /// ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π²ΠΎΠ·Π½ΠΈΠΊΡΠ΅Π΅ ΠΏΡΠΈ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ.</param> | |
336 | /// <returns>ΠΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅, ΠΊΠΎΡΠΎΡΠΎΠ΅ Π±ΡΠ΄Π΅Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡΠΈ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΈΡΡ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΡ.</returns> |
|
373 | /// <returns>ΠΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅, ΠΊΠΎΡΠΎΡΠΎΠ΅ Π±ΡΠ΄Π΅Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡΠΈ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΈΡΡ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΡ.</returns> | |
337 |
public IPromise<TNew> |
|
374 | public IPromise<TNew> Then<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler<T> error) { | |
338 | if (mapper == null) |
|
375 | if (mapper == null) | |
339 | throw new ArgumentNullException("mapper"); |
|
376 | throw new ArgumentNullException("mapper"); | |
340 |
|
377 | |||
@@ -370,8 +407,8 namespace Implab { | |||||
370 | return chained; |
|
407 | return chained; | |
371 | } |
|
408 | } | |
372 |
|
409 | |||
373 |
public IPromise<TNew> |
|
410 | public IPromise<TNew> Then<TNew>(ResultMapper<T, TNew> mapper) { | |
374 |
return |
|
411 | return Then(mapper, null); | |
375 | } |
|
412 | } | |
376 |
|
413 | |||
377 | /// <summary> |
|
414 | /// <summary> | |
@@ -384,7 +421,7 namespace Implab { | |||||
384 | /// <param name="error">ΠΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΠΎΡΠΈΠ±ΠΊΠΈ. ΠΠ°Π½Π½ΡΠΉ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΠΏΠΎΠ»ΡΡΠΈΡ |
|
421 | /// <param name="error">ΠΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΠΎΡΠΈΠ±ΠΊΠΈ. ΠΠ°Π½Π½ΡΠΉ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΠΏΠΎΠ»ΡΡΠΈΡ | |
385 | /// ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π²ΠΎΠ·Π½ΠΈΠΊΡΠ΅Π΅ ΠΏΡΠΈ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΡΠ΅ΠΊΡΠ΅ΡΠΉ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ.</param> |
|
422 | /// ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π²ΠΎΠ·Π½ΠΈΠΊΡΠ΅Π΅ ΠΏΡΠΈ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΡΠ΅ΠΊΡΠ΅ΡΠΉ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ.</param> | |
386 | /// <returns>ΠΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅, ΠΊΠΎΡΠΎΡΠΎΠ΅ Π±ΡΠ΄Π΅Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΠΎ ΠΎΠΊΠΎΠ½ΡΠ°Π½ΠΈΡ ΡΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ Π°ΡΠ½Ρ ΡΠΎΠ½Π½ΠΎΠΉ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ.</returns> |
|
423 | /// <returns>ΠΠΎΠ²ΠΎΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅, ΠΊΠΎΡΠΎΡΠΎΠ΅ Π±ΡΠ΄Π΅Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΠΎ ΠΎΠΊΠΎΠ½ΡΠ°Π½ΠΈΡ ΡΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ Π°ΡΠ½Ρ ΡΠΎΠ½Π½ΠΎΠΉ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ.</returns> | |
387 |
public IPromise<TNew> |
|
424 | public IPromise<TNew> Then<TNew>(ChainedOperation<T, TNew> chained, ErrorHandler<T> error) { | |
388 |
|
425 | |||
389 | // ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ° Π² ΡΠΎΠΌ, ΡΡΠΎ Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ ΡΠ²ΡΠ·ΡΠ²Π°Π½ΠΈΡ Π΅ΡΠ΅ Π½Π΅ Π½Π°ΡΠ°ΡΠ° Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½Π°Ρ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΡ, ΠΏΠΎΡΡΠΎΠΌΡ Π½ΡΠΆΠ½ΠΎ |
|
426 | // ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ° Π² ΡΠΎΠΌ, ΡΡΠΎ Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ ΡΠ²ΡΠ·ΡΠ²Π°Π½ΠΈΡ Π΅ΡΠ΅ Π½Π΅ Π½Π°ΡΠ°ΡΠ° Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½Π°Ρ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΡ, ΠΏΠΎΡΡΠΎΠΌΡ Π½ΡΠΆΠ½ΠΎ | |
390 | // ΡΠΎΠ·Π΄Π°ΡΡ ΠΏΠΎΡΡΠ΅Π΄Π½ΠΈΠΊΠ°, ΠΊ ΠΊΠΎΡΠΎΡΠΎΠΌΡ Π±ΡΠ΄ΡΡ ΠΏΠΎΠ΄Π²ΡΠ·ΡΠ²Π°ΡΡΡΡ ΡΠ»Π΅Π΄ΡΡΡΠΈΠ΅ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ. |
|
427 | // ΡΠΎΠ·Π΄Π°ΡΡ ΠΏΠΎΡΡΠ΅Π΄Π½ΠΈΠΊΠ°, ΠΊ ΠΊΠΎΡΠΎΡΠΎΠΌΡ Π±ΡΠ΄ΡΡ ΠΏΠΎΠ΄Π²ΡΠ·ΡΠ²Π°ΡΡΡΡ ΡΠ»Π΅Π΄ΡΡΡΠΈΠ΅ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ. | |
@@ -442,8 +479,8 namespace Implab { | |||||
442 | return medium; |
|
479 | return medium; | |
443 | } |
|
480 | } | |
444 |
|
481 | |||
445 |
public IPromise<TNew> |
|
482 | public IPromise<TNew> Then<TNew>(ChainedOperation<T, TNew> chained) { | |
446 |
return |
|
483 | return Then(chained, null); | |
447 | } |
|
484 | } | |
448 |
|
485 | |||
449 | public IPromise<T> Cancelled(Action handler) { |
|
486 | public IPromise<T> Cancelled(Action handler) { | |
@@ -478,7 +515,7 namespace Implab { | |||||
478 | /// <typeparam name="T2"></typeparam> |
|
515 | /// <typeparam name="T2"></typeparam> | |
479 | /// <returns></returns> |
|
516 | /// <returns></returns> | |
480 | public IPromise<T2> Cast<T2>() { |
|
517 | public IPromise<T2> Cast<T2>() { | |
481 |
return |
|
518 | return Then(x => (T2)(object)x, null); | |
482 | } |
|
519 | } | |
483 |
|
520 | |||
484 | /// <summary> |
|
521 | /// <summary> | |
@@ -504,8 +541,7 namespace Implab { | |||||
504 | /// <returns>Π Π΅Π·ΡΠ»ΡΡΠ°Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΡ</returns> |
|
541 | /// <returns>Π Π΅Π·ΡΠ»ΡΡΠ°Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΡ</returns> | |
505 | public T Join(int timeout) { |
|
542 | public T Join(int timeout) { | |
506 | var evt = new ManualResetEvent(false); |
|
543 | var evt = new ManualResetEvent(false); | |
507 |
|
|
544 | Finally(() => evt.Set()); | |
508 | Cancelled(() => evt.Set()); |
|
|||
509 |
|
545 | |||
510 | if (!evt.WaitOne(timeout, true)) |
|
546 | if (!evt.WaitOne(timeout, true)) | |
511 | throw new TimeoutException(); |
|
547 | throw new TimeoutException(); | |
@@ -704,10 +740,6 namespace Implab { | |||||
704 | return Error(error); |
|
740 | return Error(error); | |
705 | } |
|
741 | } | |
706 |
|
742 | |||
707 | IPromise IPromise.Anyway(Action handler) { |
|
|||
708 | return Anyway(handler); |
|
|||
709 | } |
|
|||
710 |
|
||||
711 | IPromise IPromise.Finally(Action handler) { |
|
743 | IPromise IPromise.Finally(Action handler) { | |
712 | return Finally(handler); |
|
744 | return Finally(handler); | |
713 | } |
|
745 | } |
@@ -1,8 +1,13 | |||||
1 | using System.Threading; |
|
1 | using System.Threading; | |
|
2 | using System; | |||
|
3 | #if NET_4_5 | |||
|
4 | using System.Threading.Tasks; | |||
|
5 | #endif | |||
2 |
|
6 | |||
3 | namespace Implab { |
|
7 | namespace Implab { | |
4 | public static class PromiseExtensions { |
|
8 | public static class PromiseExtensions { | |
5 | public static IPromise<T> DispatchToCurrentContext<T>(this IPromise<T> that) { |
|
9 | public static IPromise<T> DispatchToCurrentContext<T>(this IPromise<T> that) { | |
|
10 | Safe.ArgumentNotNull(that, "that"); | |||
6 | var context = SynchronizationContext.Current; |
|
11 | var context = SynchronizationContext.Current; | |
7 | if (context == null) |
|
12 | if (context == null) | |
8 | return that; |
|
13 | return that; | |
@@ -20,6 +25,7 namespace Implab { | |||||
20 | } |
|
25 | } | |
21 |
|
26 | |||
22 | public static IPromise<T> DispatchToContext<T>(this IPromise<T> that, SynchronizationContext context) { |
|
27 | public static IPromise<T> DispatchToContext<T>(this IPromise<T> that, SynchronizationContext context) { | |
|
28 | Safe.ArgumentNotNull(that, "that"); | |||
23 | Safe.ArgumentNotNull(context, "context"); |
|
29 | Safe.ArgumentNotNull(context, "context"); | |
24 |
|
30 | |||
25 | var p = new SyncContextPromise<T>(context, that, true); |
|
31 | var p = new SyncContextPromise<T>(context, that, true); | |
@@ -33,6 +39,31 namespace Implab { | |||||
33 | ); |
|
39 | ); | |
34 | return p; |
|
40 | return p; | |
35 | } |
|
41 | } | |
|
42 | ||||
|
43 | public static AsyncCallback AsyncCallback<T>(this Promise<T> that, Func<IAsyncResult,T> callback) { | |||
|
44 | Safe.ArgumentNotNull(that, "that"); | |||
|
45 | Safe.ArgumentNotNull(callback, "callback"); | |||
|
46 | return ar => { | |||
|
47 | try { | |||
|
48 | that.Resolve(callback(ar)); | |||
|
49 | } catch (Exception err) { | |||
|
50 | that.Reject(err); | |||
|
51 | } | |||
|
52 | }; | |||
|
53 | } | |||
|
54 | ||||
|
55 | #if NET_4_5 | |||
|
56 | ||||
|
57 | public static Task<T> GetTask<T>(this IPromise<T> that) { | |||
|
58 | Safe.ArgumentNotNull(that, "that"); | |||
|
59 | var tcs = new TaskCompletionSource<T>(); | |||
|
60 | ||||
|
61 | that.Last(tcs.SetResult, tcs.SetException, tcs.SetCanceled); | |||
|
62 | ||||
|
63 | return tcs.Task; | |||
|
64 | } | |||
|
65 | ||||
|
66 | #endif | |||
36 | } |
|
67 | } | |
37 | } |
|
68 | } | |
38 |
|
69 |
General Comments 0
You need to be logged in to leave comments.
Login now