Auto status change to "Under Review"
| @@ -0,0 +1,4 | |||||
|
|
1 | <?xml version="1.0" encoding="utf-8"?> | |||
|
|
2 | <packages> | |||
|
|
3 | <package id="NUnit" version="2.6.4" targetFramework="net45" /> | |||
|
|
4 | </packages> No newline at end of file | |||
| @@ -0,0 +1,16 | |||||
|
|
1 | using System; | |||
|
|
2 | ||||
|
|
3 | namespace Implab.Components | |||
|
|
4 | { | |||
|
|
5 | public class StateChangeEventArgs { | |||
|
|
6 | /// <summary> | |||
|
|
7 | /// The error information if any | |||
|
|
8 | /// </summary> | |||
|
|
9 | public Exception LastError { get; set; } | |||
|
|
10 | ||||
|
|
11 | /// <summary> | |||
|
|
12 | /// The state of the service corresponding to this event | |||
|
|
13 | /// </summary> | |||
|
|
14 | public ExecutionState State { get; set; } | |||
|
|
15 | } | |||
|
|
16 | } | |||
| @@ -336,7 +336,7 namespace Implab.Test { | |||||
| 336 | Console.WriteLine("done reader #2: {0} ms", Environment.TickCount - t1); |
|
336 | Console.WriteLine("done reader #2: {0} ms", Environment.TickCount - t1); | |
| 337 | } |
|
337 | } | |
| 338 | ) |
|
338 | ) | |
| 339 |
. |
|
339 | .PromiseAll() | |
| 340 | .Join(); |
|
340 | .Join(); | |
| 341 |
|
341 | |||
| 342 | Assert.AreEqual(count * 3, res1 + res2); |
|
342 | Assert.AreEqual(count * 3, res1 + res2); | |
| @@ -414,7 +414,7 namespace Implab.Test { | |||||
| 414 | Console.WriteLine("done reader #2: {0} ms", Environment.TickCount - t1); |
|
414 | Console.WriteLine("done reader #2: {0} ms", Environment.TickCount - t1); | |
| 415 | } |
|
415 | } | |
| 416 | ) |
|
416 | ) | |
| 417 |
. |
|
417 | .PromiseAll() | |
| 418 | .Join(); |
|
418 | .Join(); | |
| 419 |
|
419 | |||
| 420 | Assert.AreEqual(summ , r1 + r2); |
|
420 | Assert.AreEqual(summ , r1 + r2); | |
| @@ -490,7 +490,7 namespace Implab.Test { | |||||
| 490 | Console.WriteLine("done reader #2: {0} ms, avg chunk size: {1}", Environment.TickCount - t1, avgchunk); |
|
490 | Console.WriteLine("done reader #2: {0} ms, avg chunk size: {1}", Environment.TickCount - t1, avgchunk); | |
| 491 | } |
|
491 | } | |
| 492 | ) |
|
492 | ) | |
| 493 |
. |
|
493 | .PromiseAll() | |
| 494 | .Join(); |
|
494 | .Join(); | |
| 495 |
|
495 | |||
| 496 | Assert.AreEqual(summ , r1 + r2); |
|
496 | Assert.AreEqual(summ , r1 + r2); | |
| @@ -593,7 +593,7 namespace Implab.Test { | |||||
| 593 | Console.WriteLine("done reader #2: {0} ms, {1} items", Environment.TickCount - t1, count); |
|
593 | Console.WriteLine("done reader #2: {0} ms, {1} items", Environment.TickCount - t1, count); | |
| 594 | } |
|
594 | } | |
| 595 | ) |
|
595 | ) | |
| 596 |
. |
|
596 | .PromiseAll() | |
| 597 | .Join(); |
|
597 | .Join(); | |
| 598 |
|
598 | |||
| 599 | Assert.AreEqual(summ , r1 + r2); |
|
599 | Assert.AreEqual(summ , r1 + r2); | |
| @@ -835,7 +835,7 namespace Implab.Test { | |||||
| 835 | log.Enqueue("Writer #1 lock released"); |
|
835 | log.Enqueue("Writer #1 lock released"); | |
| 836 | } |
|
836 | } | |
| 837 | } |
|
837 | } | |
| 838 |
). |
|
838 | ).PromiseAll().Join(1000); | |
| 839 | log.Enqueue("Done"); |
|
839 | log.Enqueue("Done"); | |
| 840 | } catch(Exception error) { |
|
840 | } catch(Exception error) { | |
| 841 | log.Enqueue(error.Message); |
|
841 | log.Enqueue(error.Message); | |
| @@ -1,52 +1,55 | |||||
| 1 | <?xml version="1.0" encoding="utf-8"?> |
|
1 | <?xml version="1.0" encoding="utf-8"?> | |
| 2 | <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|
2 | <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |
| 3 | <PropertyGroup> |
|
3 | <PropertyGroup> | |
| 4 | <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
|
4 | <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | |
| 5 | <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
|
5 | <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | |
| 6 | <ProductVersion>8.0.30703</ProductVersion> |
|
6 | <ProductVersion>8.0.30703</ProductVersion> | |
| 7 | <SchemaVersion>2.0</SchemaVersion> |
|
7 | <SchemaVersion>2.0</SchemaVersion> | |
| 8 | <ProjectGuid>{4D364996-7ECD-4193-8F90-F223FFEA49DA}</ProjectGuid> |
|
8 | <ProjectGuid>{4D364996-7ECD-4193-8F90-F223FFEA49DA}</ProjectGuid> | |
| 9 | <OutputType>Library</OutputType> |
|
9 | <OutputType>Library</OutputType> | |
| 10 | <RootNamespace>Implab.Format.Test</RootNamespace> |
|
10 | <RootNamespace>Implab.Format.Test</RootNamespace> | |
| 11 | <AssemblyName>Implab.Format.Test</AssemblyName> |
|
11 | <AssemblyName>Implab.Format.Test</AssemblyName> | |
| 12 | <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> |
|
12 | <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> | |
| 13 | <ReleaseVersion>0.2</ReleaseVersion> |
|
13 | <ReleaseVersion>0.2</ReleaseVersion> | |
| 14 | </PropertyGroup> |
|
14 | </PropertyGroup> | |
| 15 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
|
15 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | |
| 16 | <DebugSymbols>true</DebugSymbols> |
|
16 | <DebugSymbols>true</DebugSymbols> | |
| 17 | <DebugType>full</DebugType> |
|
17 | <DebugType>full</DebugType> | |
| 18 | <Optimize>false</Optimize> |
|
18 | <Optimize>false</Optimize> | |
| 19 | <OutputPath>bin\Debug</OutputPath> |
|
19 | <OutputPath>bin\Debug</OutputPath> | |
| 20 | <DefineConstants>DEBUG;</DefineConstants> |
|
20 | <DefineConstants>DEBUG;</DefineConstants> | |
| 21 | <ErrorReport>prompt</ErrorReport> |
|
21 | <ErrorReport>prompt</ErrorReport> | |
| 22 | <WarningLevel>4</WarningLevel> |
|
22 | <WarningLevel>4</WarningLevel> | |
| 23 | <ConsolePause>false</ConsolePause> |
|
23 | <ConsolePause>false</ConsolePause> | |
| 24 | </PropertyGroup> |
|
24 | </PropertyGroup> | |
| 25 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
|
25 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | |
| 26 | <DebugType>full</DebugType> |
|
26 | <DebugType>full</DebugType> | |
| 27 | <Optimize>true</Optimize> |
|
27 | <Optimize>true</Optimize> | |
| 28 | <OutputPath>bin\Release</OutputPath> |
|
28 | <OutputPath>bin\Release</OutputPath> | |
| 29 | <ErrorReport>prompt</ErrorReport> |
|
29 | <ErrorReport>prompt</ErrorReport> | |
| 30 | <WarningLevel>4</WarningLevel> |
|
30 | <WarningLevel>4</WarningLevel> | |
| 31 | <ConsolePause>false</ConsolePause> |
|
31 | <ConsolePause>false</ConsolePause> | |
| 32 | </PropertyGroup> |
|
32 | </PropertyGroup> | |
| 33 | <ItemGroup> |
|
33 | <ItemGroup> | |
| 34 | <Reference Include="System" /> |
|
34 | <Reference Include="System" /> | |
| 35 | <Reference Include="nunit.framework"> |
|
35 | <Reference Include="nunit.framework"> | |
| 36 | <HintPath>..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath> |
|
36 | <HintPath>..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath> | |
| 37 | </Reference> |
|
37 | </Reference> | |
| 38 | </ItemGroup> |
|
38 | </ItemGroup> | |
| 39 | <ItemGroup> |
|
39 | <ItemGroup> | |
| 40 | <Compile Include="JsonTests.cs" /> |
|
40 | <Compile Include="JsonTests.cs" /> | |
| 41 | </ItemGroup> |
|
41 | </ItemGroup> | |
| 42 | <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> |
|
42 | <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> | |
| 43 | <ItemGroup> |
|
43 | <ItemGroup> | |
| 44 | <ProjectReference Include="..\..\Implab\Implab.csproj"> |
|
44 | <ProjectReference Include="..\..\Implab\Implab.csproj"> | |
| 45 | <Project>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</Project> |
|
45 | <Project>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</Project> | |
| 46 | <Name>Implab</Name> |
|
46 | <Name>Implab</Name> | |
| 47 | </ProjectReference> |
|
47 | </ProjectReference> | |
| 48 | </ItemGroup> |
|
48 | </ItemGroup> | |
| 49 | <ItemGroup> |
|
49 | <ItemGroup> | |
| 50 | <None Include="packages.config" /> |
|
50 | <None Include="packages.config" /> | |
| 51 | </ItemGroup> |
|
51 | </ItemGroup> | |
|
|
52 | <ItemGroup> | |||
|
|
53 | <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> | |||
|
|
54 | </ItemGroup> | |||
| 52 | </Project> No newline at end of file |
|
55 | </Project> | |
| @@ -1,75 +1,81 | |||||
| 1 | <?xml version="1.0" encoding="utf-8"?> |
|
1 | <?xml version="1.0" encoding="utf-8"?> | |
| 2 | <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|
2 | <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |
| 3 | <PropertyGroup> |
|
3 | <PropertyGroup> | |
| 4 | <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
|
4 | <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | |
| 5 | <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
|
5 | <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | |
| 6 | <ProductVersion>8.0.30703</ProductVersion> |
|
6 | <ProductVersion>8.0.30703</ProductVersion> | |
| 7 | <SchemaVersion>2.0</SchemaVersion> |
|
7 | <SchemaVersion>2.0</SchemaVersion> | |
| 8 | <ProjectGuid>{2BD05F84-E067-4B87-9477-FDC2676A21C6}</ProjectGuid> |
|
8 | <ProjectGuid>{2BD05F84-E067-4B87-9477-FDC2676A21C6}</ProjectGuid> | |
| 9 | <OutputType>Library</OutputType> |
|
9 | <OutputType>Library</OutputType> | |
| 10 | <RootNamespace>Implab.Test</RootNamespace> |
|
10 | <RootNamespace>Implab.Test</RootNamespace> | |
| 11 | <AssemblyName>Implab.Test</AssemblyName> |
|
11 | <AssemblyName>Implab.Test</AssemblyName> | |
| 12 | <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> |
|
12 | <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> | |
| 13 | <ReleaseVersion>0.2</ReleaseVersion> |
|
13 | <ReleaseVersion>0.2</ReleaseVersion> | |
| 14 | </PropertyGroup> |
|
14 | </PropertyGroup> | |
| 15 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
|
15 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | |
| 16 | <DebugSymbols>true</DebugSymbols> |
|
16 | <DebugSymbols>true</DebugSymbols> | |
| 17 | <DebugType>full</DebugType> |
|
17 | <DebugType>full</DebugType> | |
| 18 | <Optimize>false</Optimize> |
|
18 | <Optimize>false</Optimize> | |
| 19 | <OutputPath>bin\Debug</OutputPath> |
|
19 | <OutputPath>bin\Debug</OutputPath> | |
| 20 | <DefineConstants>DEBUG;MONO</DefineConstants> |
|
20 | <DefineConstants>DEBUG;MONO</DefineConstants> | |
| 21 | <ErrorReport>prompt</ErrorReport> |
|
21 | <ErrorReport>prompt</ErrorReport> | |
| 22 | <WarningLevel>4</WarningLevel> |
|
22 | <WarningLevel>4</WarningLevel> | |
| 23 | <ConsolePause>false</ConsolePause> |
|
23 | <ConsolePause>false</ConsolePause> | |
| 24 | </PropertyGroup> |
|
24 | </PropertyGroup> | |
| 25 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
|
25 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | |
| 26 | <Optimize>true</Optimize> |
|
26 | <Optimize>true</Optimize> | |
| 27 | <OutputPath>bin\Release</OutputPath> |
|
27 | <OutputPath>bin\Release</OutputPath> | |
| 28 | <ErrorReport>prompt</ErrorReport> |
|
28 | <ErrorReport>prompt</ErrorReport> | |
| 29 | <WarningLevel>4</WarningLevel> |
|
29 | <WarningLevel>4</WarningLevel> | |
| 30 | <ConsolePause>false</ConsolePause> |
|
30 | <ConsolePause>false</ConsolePause> | |
| 31 | <DefineConstants>MONO</DefineConstants> |
|
31 | <DefineConstants>MONO</DefineConstants> | |
| 32 | </PropertyGroup> |
|
32 | </PropertyGroup> | |
| 33 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' "> |
|
33 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' "> | |
| 34 | <DebugSymbols>true</DebugSymbols> |
|
34 | <DebugSymbols>true</DebugSymbols> | |
| 35 | <DebugType>full</DebugType> |
|
35 | <DebugType>full</DebugType> | |
| 36 | <Optimize>false</Optimize> |
|
36 | <Optimize>false</Optimize> | |
| 37 | <OutputPath>bin\Debug</OutputPath> |
|
37 | <OutputPath>bin\Debug</OutputPath> | |
| 38 | <DefineConstants>DEBUG;TRACE;NET_4_5;MONO</DefineConstants> |
|
38 | <DefineConstants>DEBUG;TRACE;NET_4_5;MONO</DefineConstants> | |
| 39 | <ErrorReport>prompt</ErrorReport> |
|
39 | <ErrorReport>prompt</ErrorReport> | |
| 40 | <WarningLevel>4</WarningLevel> |
|
40 | <WarningLevel>4</WarningLevel> | |
| 41 | <ConsolePause>false</ConsolePause> |
|
41 | <ConsolePause>false</ConsolePause> | |
| 42 | </PropertyGroup> |
|
42 | </PropertyGroup> | |
| 43 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' "> |
|
43 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' "> | |
| 44 | <Optimize>true</Optimize> |
|
44 | <Optimize>true</Optimize> | |
| 45 | <OutputPath>bin\Release</OutputPath> |
|
45 | <OutputPath>bin\Release</OutputPath> | |
| 46 | <DefineConstants>NET_4_5;MONO</DefineConstants> |
|
46 | <DefineConstants>NET_4_5;MONO</DefineConstants> | |
| 47 | <ErrorReport>prompt</ErrorReport> |
|
47 | <ErrorReport>prompt</ErrorReport> | |
| 48 | <WarningLevel>4</WarningLevel> |
|
48 | <WarningLevel>4</WarningLevel> | |
| 49 | <ConsolePause>false</ConsolePause> |
|
49 | <ConsolePause>false</ConsolePause> | |
| 50 | </PropertyGroup> |
|
50 | </PropertyGroup> | |
| 51 | <ItemGroup> |
|
51 | <ItemGroup> | |
| 52 | <Reference Include="System" /> |
|
52 | <Reference Include="nunit.framework, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL"> | |
| 53 | <Reference Include="nunit.framework" /> |
|
53 | <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath> | |
| 54 | </ItemGroup> |
|
54 | <Private>True</Private> | |
| 55 | <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> |
|
55 | </Reference> | |
| 56 | <ItemGroup> |
|
56 | <Reference Include="System" /> | |
| 57 | <Compile Include="AsyncTests.cs" /> |
|
57 | </ItemGroup> | |
| 58 | <Compile Include="PromiseHelper.cs" /> |
|
58 | <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> | |
| 59 | <Compile Include="Properties\AssemblyInfo.cs" /> |
|
59 | <ItemGroup> | |
| 60 |
<Compile Include=" |
|
60 | <Compile Include="AsyncTests.cs" /> | |
| 61 |
<Compile Include=" |
|
61 | <Compile Include="PromiseHelper.cs" /> | |
| 62 |
<Compile Include="P |
|
62 | <Compile Include="Properties\AssemblyInfo.cs" /> | |
| 63 |
<Compile Include=" |
|
63 | <Compile Include="CancelationTests.cs" /> | |
| 64 |
<Compile Include=" |
|
64 | <Compile Include="RunnableComponentTests.cs" /> | |
| 65 | </ItemGroup> |
|
65 | <Compile Include="PollingComponentTests.cs" /> | |
| 66 | <ItemGroup> |
|
66 | <Compile Include="Mock\MockRunnableComponent.cs" /> | |
| 67 | <ProjectReference Include="..\Implab\Implab.csproj"> |
|
67 | <Compile Include="Mock\MockPollingComponent.cs" /> | |
| 68 | <Project>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</Project> |
|
68 | </ItemGroup> | |
| 69 | <Name>Implab</Name> |
|
69 | <ItemGroup> | |
| 70 | </ProjectReference> |
|
70 | <ProjectReference Include="..\Implab\Implab.csproj"> | |
| 71 | </ItemGroup> |
|
71 | <Project>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</Project> | |
| 72 | <ItemGroup> |
|
72 | <Name>Implab</Name> | |
| 73 | <Folder Include="Mock\" /> |
|
73 | </ProjectReference> | |
| 74 | </ItemGroup> |
|
74 | </ItemGroup> | |
|
|
75 | <ItemGroup> | |||
|
|
76 | <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> | |||
|
|
77 | </ItemGroup> | |||
|
|
78 | <ItemGroup> | |||
|
|
79 | <None Include="packages.config" /> | |||
|
|
80 | </ItemGroup> | |||
| 75 | </Project> No newline at end of file |
|
81 | </Project> | |
| @@ -50,7 +50,7 namespace Implab.Test.Mock { | |||||
| 50 | } |
|
50 | } | |
| 51 |
|
51 | |||
| 52 | protected override IPromise OnTick(ICancellationToken cancellationToken) { |
|
52 | protected override IPromise OnTick(ICancellationToken cancellationToken) { | |
| 53 |
return MockTick != null ? Safe.Run(() => MockTick(cancellationToken)) : Promise.S |
|
53 | return MockTick != null ? Safe.Run(() => MockTick(cancellationToken)) : Promise.Success; | |
| 54 | } |
|
54 | } | |
| 55 |
|
55 | |||
| 56 | protected override void OnTickCancel(Exception error) { |
|
56 | protected override void OnTickCancel(Exception error) { | |
| @@ -6,6 +6,9 namespace Implab.Test.Mock { | |||||
| 6 | public MockRunnableComponent(bool initialized) : base(initialized) { |
|
6 | public MockRunnableComponent(bool initialized) : base(initialized) { | |
| 7 | } |
|
7 | } | |
| 8 |
|
8 | |||
|
|
9 | public MockRunnableComponent(bool initialized, bool reusable) : base(initialized, reusable) { | |||
|
|
10 | } | |||
|
|
11 | ||||
| 9 | public Action MockInit { |
|
12 | public Action MockInit { | |
| 10 | get; |
|
13 | get; | |
| 11 | set; |
|
14 | set; | |
| @@ -21,6 +24,11 namespace Implab.Test.Mock { | |||||
| 21 | set; |
|
24 | set; | |
| 22 | } |
|
25 | } | |
| 23 |
|
26 | |||
|
|
27 | public Action<bool, Exception> MockDispose { | |||
|
|
28 | get; | |||
|
|
29 | set; | |||
|
|
30 | } | |||
|
|
31 | ||||
| 24 | protected override IPromise OnStart() { |
|
32 | protected override IPromise OnStart() { | |
| 25 | return MockStart != null ? Safe.Run(MockStart).Chain(base.OnStart) : Safe.Run(base.OnStart); |
|
33 | return MockStart != null ? Safe.Run(MockStart).Chain(base.OnStart) : Safe.Run(base.OnStart); | |
| 26 | } |
|
34 | } | |
| @@ -33,6 +41,12 namespace Implab.Test.Mock { | |||||
| 33 | if (MockInit != null) |
|
41 | if (MockInit != null) | |
| 34 | MockInit(); |
|
42 | MockInit(); | |
| 35 | } |
|
43 | } | |
|
|
44 | ||||
|
|
45 | protected override void Dispose(bool disposing, Exception lastError) { | |||
|
|
46 | if (MockDispose != null) | |||
|
|
47 | MockDispose(disposing, lastError); | |||
|
|
48 | base.Dispose(disposing, lastError); | |||
|
|
49 | } | |||
| 36 | } |
|
50 | } | |
| 37 | } |
|
51 | } | |
| 38 |
|
52 | |||
| @@ -36,7 +36,7 namespace Implab.Test { | |||||
| 36 |
|
36 | |||
| 37 | Assert.AreEqual(ExecutionState.Created, comp.State); |
|
37 | Assert.AreEqual(ExecutionState.Created, comp.State); | |
| 38 |
|
38 | |||
| 39 | comp.Init(); |
|
39 | comp.Initialize(); | |
| 40 |
|
40 | |||
| 41 | Assert.AreEqual(ExecutionState.Ready, comp.State); |
|
41 | Assert.AreEqual(ExecutionState.Ready, comp.State); | |
| 42 |
|
42 | |||
| @@ -57,7 +57,7 namespace Implab.Test { | |||||
| 57 | var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true); |
|
57 | var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true); | |
| 58 | comp.MockTick = ct => { |
|
58 | comp.MockTick = ct => { | |
| 59 | signal.Set(); |
|
59 | signal.Set(); | |
| 60 |
return Promise.S |
|
60 | return Promise.Success; | |
| 61 | }; |
|
61 | }; | |
| 62 |
|
62 | |||
| 63 | comp.Start().Join(1000); |
|
63 | comp.Start().Join(1000); | |
| @@ -39,7 +39,7 namespace Implab.Test { | |||||
| 39 |
|
39 | |||
| 40 | Assert.AreEqual(ExecutionState.Created, comp.State); |
|
40 | Assert.AreEqual(ExecutionState.Created, comp.State); | |
| 41 |
|
41 | |||
| 42 | comp.Init(); |
|
42 | comp.Initialize(); | |
| 43 |
|
43 | |||
| 44 | Assert.AreEqual(ExecutionState.Ready, comp.State); |
|
44 | Assert.AreEqual(ExecutionState.Ready, comp.State); | |
| 45 |
|
45 | |||
| @@ -65,7 +65,7 namespace Implab.Test { | |||||
| 65 | ShouldThrow(() => comp.Stop()); |
|
65 | ShouldThrow(() => comp.Stop()); | |
| 66 | Assert.AreEqual(ExecutionState.Created, comp.State); |
|
66 | Assert.AreEqual(ExecutionState.Created, comp.State); | |
| 67 |
|
67 | |||
| 68 | ShouldThrow(comp.Init); |
|
68 | ShouldThrow(comp.Initialize); | |
| 69 |
|
69 | |||
| 70 | Assert.AreEqual(ExecutionState.Failed, comp.State); |
|
70 | Assert.AreEqual(ExecutionState.Failed, comp.State); | |
| 71 |
|
71 | |||
| @@ -85,12 +85,77 namespace Implab.Test { | |||||
| 85 |
|
85 | |||
| 86 | ShouldThrow(() => comp.Start()); |
|
86 | ShouldThrow(() => comp.Start()); | |
| 87 | ShouldThrow(() => comp.Stop()); |
|
87 | ShouldThrow(() => comp.Stop()); | |
| 88 | ShouldThrow(comp.Init); |
|
88 | ShouldThrow(comp.Initialize); | |
| 89 |
|
89 | |||
| 90 | Assert.AreEqual(ExecutionState.Disposed, comp.State); |
|
90 | Assert.AreEqual(ExecutionState.Disposed, comp.State); | |
| 91 | } |
|
91 | } | |
| 92 |
|
92 | |||
| 93 | [TestMethod] |
|
93 | [TestMethod] | |
|
|
94 | public void ShouldCallDisposeOnStop() { | |||
|
|
95 | var comp = new MockRunnableComponent(true); | |||
|
|
96 | ||||
|
|
97 | bool disposed = false; | |||
|
|
98 | comp.MockDispose = (disposing, error) => { | |||
|
|
99 | disposed = true; | |||
|
|
100 | }; | |||
|
|
101 | ||||
|
|
102 | comp.Start().Join(1000); | |||
|
|
103 | comp.Stop().Join(1000); | |||
|
|
104 | ||||
|
|
105 | ShouldThrow(() => comp.Start()); | |||
|
|
106 | ShouldThrow(() => comp.Stop()); | |||
|
|
107 | ShouldThrow(comp.Initialize); | |||
|
|
108 | ||||
|
|
109 | Assert.AreEqual(ExecutionState.Disposed, comp.State); | |||
|
|
110 | Assert.IsTrue(disposed); | |||
|
|
111 | } | |||
|
|
112 | ||||
|
|
113 | [TestMethod] | |||
|
|
114 | public void ShouldNotCallDisposeOnStop() { | |||
|
|
115 | var comp = new MockRunnableComponent(true, true); | |||
|
|
116 | ||||
|
|
117 | bool disposed = false; | |||
|
|
118 | comp.MockDispose = (disposing, error) => { | |||
|
|
119 | disposed = true; | |||
|
|
120 | }; | |||
|
|
121 | ||||
|
|
122 | comp.Start().Join(1000); | |||
|
|
123 | comp.Stop().Join(1000); | |||
|
|
124 | ||||
|
|
125 | Assert.AreEqual(ExecutionState.Ready, comp.State); | |||
|
|
126 | Assert.IsFalse(disposed); | |||
|
|
127 | } | |||
|
|
128 | ||||
|
|
129 | [TestMethod] | |||
|
|
130 | public void SelfDisposeOnStop() { | |||
|
|
131 | var comp = new MockRunnableComponent(true, true); | |||
|
|
132 | ||||
|
|
133 | bool disposed = false; | |||
|
|
134 | Exception lastError = null; | |||
|
|
135 | comp.MockDispose = (disposing, error) => { | |||
|
|
136 | disposed = true; | |||
|
|
137 | lastError = error; | |||
|
|
138 | }; | |||
|
|
139 | ||||
|
|
140 | comp.Start().Join(1000); | |||
|
|
141 | comp.Stop().Join(1000); | |||
|
|
142 | ||||
|
|
143 | Assert.AreEqual(ExecutionState.Ready, comp.State); | |||
|
|
144 | Assert.IsFalse(disposed); | |||
|
|
145 | ||||
|
|
146 | comp.MockStop = () => { | |||
|
|
147 | comp.Dispose(); | |||
|
|
148 | return Promise.Success; | |||
|
|
149 | }; | |||
|
|
150 | ||||
|
|
151 | comp.Start().Join(1000); | |||
|
|
152 | comp.Stop().Join(1000); | |||
|
|
153 | ||||
|
|
154 | Assert.AreEqual(ExecutionState.Disposed, comp.State); | |||
|
|
155 | Assert.IsTrue(disposed); | |||
|
|
156 | } | |||
|
|
157 | ||||
|
|
158 | [TestMethod] | |||
| 94 | public void StartCancelTest() { |
|
159 | public void StartCancelTest() { | |
| 95 | var comp = new MockRunnableComponent(true) { |
|
160 | var comp = new MockRunnableComponent(true) { | |
| 96 | MockStart = () => PromiseHelper.Sleep(100000, 0) |
|
161 | MockStart = () => PromiseHelper.Sleep(100000, 0) | |
| @@ -28,6 +28,14 namespace Implab.Automaton { | |||||
| 28 | public override int GetHashCode() { |
|
28 | public override int GetHashCode() { | |
| 29 | return s1 + s2 + edge; |
|
29 | return s1 + s2 + edge; | |
| 30 | } |
|
30 | } | |
|
|
31 | ||||
|
|
32 | public static bool operator == (AutomatonTransition rv, AutomatonTransition lv) { | |||
|
|
33 | return rv.Equals(lv); | |||
|
|
34 | } | |||
|
|
35 | ||||
|
|
36 | public static bool operator !=(AutomatonTransition rv, AutomatonTransition lv) { | |||
|
|
37 | return rv.Equals(lv); | |||
|
|
38 | } | |||
| 31 | } |
|
39 | } | |
| 32 | } |
|
40 | } | |
| 33 |
|
41 | |||
| @@ -3,8 +3,8 | |||||
| 3 | namespace Implab.Components { |
|
3 | namespace Implab.Components { | |
| 4 | /// <summary> |
|
4 | /// <summary> | |
| 5 | /// Initializable components are created and initialized in two steps, first we have create the component, |
|
5 | /// Initializable components are created and initialized in two steps, first we have create the component, | |
| 6 | /// then we have to complete it's creation by calling an <see cref="Init()"/> method. All parameters needed |
|
6 | /// then we have to complete it's creation by calling an <see cref="Initialize()"/> method. All parameters needed | |
| 7 | /// to complete the initialization must be passed before the calling <see cref="Init()"/> |
|
7 | /// to complete the initialization must be passed before the calling <see cref="Initialize()"/> | |
| 8 | /// </summary> |
|
8 | /// </summary> | |
| 9 | public interface IInitializable { |
|
9 | public interface IInitializable { | |
| 10 | /// <summary> |
|
10 | /// <summary> | |
| @@ -12,10 +12,10 namespace Implab.Components { | |||||
| 12 | /// </summary> |
|
12 | /// </summary> | |
| 13 | /// <remarks> |
|
13 | /// <remarks> | |
| 14 | /// Normally virtual methods shouldn't be called from the constructor, due to the incomplete object state, but |
|
14 | /// Normally virtual methods shouldn't be called from the constructor, due to the incomplete object state, but | |
| 15 | /// they can be called from this method. This method is also usefull when we constructing a complex grpah |
|
15 | /// they can be called from this method. This method is aьуерщlso usefull when we constructing a complex grpah | |
| 16 | /// of components where cyclic references may take place. |
|
16 | /// of components where cyclic references may take place. | |
| 17 | /// </remarks> |
|
17 | /// </remarks> | |
| 18 | void Init(); |
|
18 | void Initialize(); | |
| 19 | } |
|
19 | } | |
| 20 | } |
|
20 | } | |
| 21 |
|
21 | |||
| @@ -14,6 +14,8 namespace Implab.Components { | |||||
| 14 |
|
14 | |||
| 15 | ExecutionState State { get; } |
|
15 | ExecutionState State { get; } | |
| 16 |
|
16 | |||
|
|
17 | event EventHandler<StateChangeEventArgs> StateChanged; | |||
|
|
18 | ||||
| 17 | Exception LastError { get; } |
|
19 | Exception LastError { get; } | |
| 18 | } |
|
20 | } | |
| 19 | } |
|
21 | } | |
| @@ -124,7 +124,7 namespace Implab.Components { | |||||
| 124 | /// Invoked when the timer ticks, use this method to implement your logic |
|
124 | /// Invoked when the timer ticks, use this method to implement your logic | |
| 125 | /// </summary> |
|
125 | /// </summary> | |
| 126 | protected virtual IPromise OnTick(ICancellationToken cancellationToken) { |
|
126 | protected virtual IPromise OnTick(ICancellationToken cancellationToken) { | |
| 127 |
return Promise.S |
|
127 | return Promise.Success; | |
| 128 | } |
|
128 | } | |
| 129 |
|
129 | |||
| 130 | protected override IPromise OnStop() { |
|
130 | protected override IPromise OnStop() { | |
| @@ -9,7 +9,8 namespace Implab.Components { | |||||
| 9 | Start, |
|
9 | Start, | |
| 10 | Stop, |
|
10 | Stop, | |
| 11 | Dispose, |
|
11 | Dispose, | |
| 12 |
|
|
12 | Reset, | |
|
|
13 | Last = Reset | |||
| 13 | } |
|
14 | } | |
| 14 |
|
15 | |||
| 15 | class StateMachine { |
|
16 | class StateMachine { | |
| @@ -37,9 +38,11 namespace Implab.Components { | |||||
| 37 | Edge(ExecutionState.Running, ExecutionState.Disposed, Commands.Dispose); |
|
38 | Edge(ExecutionState.Running, ExecutionState.Disposed, Commands.Dispose); | |
| 38 |
|
39 | |||
| 39 | Edge(ExecutionState.Stopping, ExecutionState.Failed, Commands.Fail); |
|
40 | Edge(ExecutionState.Stopping, ExecutionState.Failed, Commands.Fail); | |
| 40 |
Edge(ExecutionState.Stopping, ExecutionState. |
|
41 | Edge(ExecutionState.Stopping, ExecutionState.Ready, Commands.Ok); | |
|
|
42 | Edge(ExecutionState.Stopping, ExecutionState.Disposed, Commands.Dispose); | |||
| 41 |
|
43 | |||
| 42 | Edge(ExecutionState.Failed, ExecutionState.Disposed, Commands.Dispose); |
|
44 | Edge(ExecutionState.Failed, ExecutionState.Disposed, Commands.Dispose); | |
|
|
45 | Edge(ExecutionState.Failed, ExecutionState.Initializing, Commands.Reset); | |||
| 43 | } |
|
46 | } | |
| 44 |
|
47 | |||
| 45 | static void Edge(ExecutionState s1, ExecutionState s2, Commands cmd) { |
|
48 | static void Edge(ExecutionState s1, ExecutionState s2, Commands cmd) { | |
| @@ -67,11 +70,26 namespace Implab.Components { | |||||
| 67 | IPromise m_pending; |
|
70 | IPromise m_pending; | |
| 68 | Exception m_lastError; |
|
71 | Exception m_lastError; | |
| 69 |
|
72 | |||
| 70 | readonly StateMachine m_stateMachine; |
|
73 | readonly StateMachine m_stateMachine; | |
| 71 |
|
74 | readonly bool m_reusable; | ||
| 72 | protected RunnableComponent(bool initialized) { |
|
75 | public event EventHandler<StateChangeEventArgs> StateChanged; | |
|
|
76 | ||||
|
|
77 | /// <summary> | |||
|
|
78 | /// Initializes component state. | |||
|
|
79 | /// </summary> | |||
|
|
80 | /// <param name="initialized">If set, the component initial state is <see cref="ExecutionState.Ready"/> and the component is ready to start, otherwise initialization is required.</param> | |||
|
|
81 | /// <param name="reusable">If set, the component may start after it has been stopped, otherwise the component is disposed after being stopped.</param> | |||
|
|
82 | protected RunnableComponent(bool initialized, bool reusable) { | |||
| 73 | m_stateMachine = new StateMachine(initialized ? ExecutionState.Ready : ExecutionState.Created); |
|
83 | m_stateMachine = new StateMachine(initialized ? ExecutionState.Ready : ExecutionState.Created); | |
| 74 | DisposeTimeout = 10000; |
|
84 | m_reusable = reusable; | |
|
|
85 | DisposeTimeout = 10000; | |||
|
|
86 | } | |||
|
|
87 | ||||
|
|
88 | /// <summary> | |||
|
|
89 | /// Initializes component state. The component created with this constructor is not reusable, i.e. it will be disposed after stop. | |||
|
|
90 | /// </summary> | |||
|
|
91 | /// <param name="initialized">If set, the component initial state is <see cref="ExecutionState.Ready"/> and the component is ready to start, otherwise initialization is required.</param> | |||
|
|
92 | protected RunnableComponent(bool initialized) : this(initialized, false) { | |||
| 75 | } |
|
93 | } | |
| 76 |
|
94 | |||
| 77 | /// <summary> |
|
95 | /// <summary> | |
| @@ -84,49 +102,119 namespace Implab.Components { | |||||
| 84 |
|
102 | |||
| 85 | void ThrowInvalidCommand(Commands cmd) { |
|
103 | void ThrowInvalidCommand(Commands cmd) { | |
| 86 | if (m_stateMachine.State == ExecutionState.Disposed) |
|
104 | if (m_stateMachine.State == ExecutionState.Disposed) | |
| 87 | throw new ObjectDisposedException(ToString()); |
|
105 | throw new ObjectDisposedException(ToString()); | |
| 88 |
|
106 | |||
| 89 | throw new InvalidOperationException(String.Format("Commnd {0} is not allowed in the state {1}", cmd, m_stateMachine.State)); |
|
107 | throw new InvalidOperationException(String.Format("Command {0} is not allowed in the state {1}", cmd, m_stateMachine.State)); | |
|
|
108 | } | |||
|
|
109 | ||||
|
|
110 | bool MoveIfInState(Commands cmd, IPromise pending, Exception error, ExecutionState state) { | |||
|
|
111 | ExecutionState prev, current; | |||
|
|
112 | lock (m_stateMachine) { | |||
|
|
113 | if (m_stateMachine.State != state) | |||
|
|
114 | return false; | |||
|
|
115 | ||||
|
|
116 | prev = m_stateMachine.State; | |||
|
|
117 | if (!m_stateMachine.Move(cmd)) | |||
|
|
118 | ThrowInvalidCommand(cmd); | |||
|
|
119 | current = m_stateMachine.State; | |||
|
|
120 | ||||
|
|
121 | m_pending = pending; | |||
|
|
122 | m_lastError = error; | |||
|
|
123 | } | |||
|
|
124 | if (prev != current) | |||
|
|
125 | OnStateChanged(prev, current, error); | |||
|
|
126 | return true; | |||
| 90 | } |
|
127 | } | |
| 91 |
|
128 | |||
| 92 | void Move(Commands cmd) { |
|
129 | bool MoveIfPending(Commands cmd, IPromise pending, Exception error, IPromise expected) { | |
| 93 | if (!m_stateMachine.Move(cmd)) |
|
130 | ExecutionState prev, current; | |
| 94 | ThrowInvalidCommand(cmd); |
|
131 | lock (m_stateMachine) { | |
|
|
132 | if (m_pending != expected) | |||
|
|
133 | return false; | |||
|
|
134 | prev = m_stateMachine.State; | |||
|
|
135 | if (!m_stateMachine.Move(cmd)) | |||
|
|
136 | ThrowInvalidCommand(cmd); | |||
|
|
137 | current = m_stateMachine.State; | |||
|
|
138 | m_pending = pending; | |||
|
|
139 | m_lastError = error; | |||
|
|
140 | } | |||
|
|
141 | if (prev != current) | |||
|
|
142 | OnStateChanged(prev, current, error); | |||
|
|
143 | return true; | |||
|
|
144 | } | |||
|
|
145 | ||||
|
|
146 | IPromise Move(Commands cmd, IPromise pending, Exception error) { | |||
|
|
147 | ExecutionState prev, current; | |||
|
|
148 | IPromise ret; | |||
|
|
149 | lock (m_stateMachine) { | |||
|
|
150 | prev = m_stateMachine.State; | |||
|
|
151 | if (!m_stateMachine.Move(cmd)) | |||
|
|
152 | ThrowInvalidCommand(cmd); | |||
|
|
153 | current = m_stateMachine.State; | |||
|
|
154 | ||||
|
|
155 | ret = m_pending; | |||
|
|
156 | m_pending = pending; | |||
|
|
157 | m_lastError = error; | |||
|
|
158 | ||||
|
|
159 | } | |||
|
|
160 | if(prev != current) | |||
|
|
161 | OnStateChanged(prev, current, error); | |||
|
|
162 | return ret; | |||
|
|
163 | } | |||
|
|
164 | ||||
|
|
165 | protected virtual void OnStateChanged(ExecutionState previous, ExecutionState current, Exception error) { | |||
|
|
166 | var h = StateChanged; | |||
|
|
167 | if (h != null) | |||
|
|
168 | h(this, new StateChangeEventArgs { | |||
|
|
169 | State = current, | |||
|
|
170 | LastError = error | |||
|
|
171 | }); | |||
| 95 | } |
|
172 | } | |
| 96 |
|
173 | |||
| 97 | /// <summary> |
|
174 | /// <summary> | |
| 98 | /// Moves the component from running to failed state. |
|
175 | /// Moves the component from running to failed state. | |
| 99 | /// </summary> |
|
176 | /// </summary> | |
| 100 | /// <param name="error">The exception which is describing the error.</param> |
|
177 | /// <param name="error">The exception which is describing the error.</param> | |
| 101 | /// <returns>Returns true if the component is set to the failed state, false - otherwise. |
|
178 | protected bool Fail(Exception error) { | |
| 102 | /// This method works only for the running state, in any other state it will return false.</returns> |
|
179 | return MoveIfInState(Commands.Fail, null, error, ExecutionState.Running); | |
| 103 | protected bool Fail(Exception error) { |
|
|||
| 104 | lock (m_stateMachine) { |
|
|||
| 105 | if(m_stateMachine.State == ExecutionState.Running) { |
|
|||
| 106 | m_stateMachine.Move(Commands.Fail); |
|
|||
| 107 | m_lastError = error; |
|
|||
| 108 | return true; |
|
|||
| 109 | } |
|
|||
| 110 | } |
|
|||
| 111 | return false; |
|
|||
| 112 | } |
|
180 | } | |
| 113 |
|
181 | |||
| 114 | void Invoke(Commands cmd, Action action) { |
|
182 | /// <summary> | |
| 115 | lock (m_stateMachine) |
|
183 | /// Tries to reset <see cref="ExecutionState.Failed"/> state to <see cref="ExecutionState.Ready"/>. | |
| 116 | Move(cmd); |
|
184 | /// </summary> | |
| 117 |
|
185 | /// <returns>True if component is reset to <see cref="ExecutionState.Ready"/>, false if the componet wasn't | ||
|
|
186 | /// in <see cref="ExecutionState.Failed"/> state.</returns> | |||
|
|
187 | /// <remarks> | |||
|
|
188 | /// This method checks the current state of the component and if it's in <see cref="ExecutionState.Failed"/> | |||
|
|
189 | /// moves component to <see cref="ExecutionState.Initializing"/>. | |||
|
|
190 | /// The <see cref="OnResetState()"/> is called and if this method completes succesfully the component moved | |||
|
|
191 | /// to <see cref="ExecutionState.Ready"/> state, otherwise the component is moved to <see cref="ExecutionState.Failed"/> | |||
|
|
192 | /// state. If <see cref="OnResetState()"/> throws an exception it will be propagated by this method to the caller. | |||
|
|
193 | /// </remarks> | |||
|
|
194 | protected bool ResetState() { | |||
|
|
195 | if (!MoveIfInState(Commands.Reset, null, null, ExecutionState.Failed)) | |||
|
|
196 | return false; | |||
|
|
197 | ||||
| 118 | try { |
|
198 | try { | |
| 119 |
|
|
199 | OnResetState(); | |
| 120 | lock(m_stateMachine) |
|
200 | Move(Commands.Ok, null, null); | |
| 121 | Move(Commands.Ok); |
|
201 | return true; | |
| 122 |
|
||||
| 123 | } catch (Exception err) { |
|
202 | } catch (Exception err) { | |
| 124 | lock (m_stateMachine) { |
|
203 | Move(Commands.Fail, null, err); | |
| 125 | Move(Commands.Fail); |
|
|||
| 126 | m_lastError = err; |
|
|||
| 127 | } |
|
|||
| 128 | throw; |
|
204 | throw; | |
| 129 | } |
|
205 | } | |
|
|
206 | } | |||
|
|
207 | ||||
|
|
208 | /// <summary> | |||
|
|
209 | /// This method is called by <see cref="ResetState"/> to reinitialize component in the failed state. | |||
|
|
210 | /// </summary> | |||
|
|
211 | /// <remarks> | |||
|
|
212 | /// Default implementation throws <see cref="NotImplementedException"/> which will cause the component | |||
|
|
213 | /// fail to reset it's state and it left in <see cref="ExecutionState.Failed"/> state. | |||
|
|
214 | /// If this method doesn't throw exceptions the component is moved to <see cref="ExecutionState.Ready"/> state. | |||
|
|
215 | /// </remarks> | |||
|
|
216 | protected virtual void OnResetState() { | |||
|
|
217 | throw new NotImplementedException(); | |||
| 130 | } |
|
218 | } | |
| 131 |
|
219 | |||
| 132 | IPromise InvokeAsync(Commands cmd, Func<IPromise> action, Action<IPromise, IDeferred> chain) { |
|
220 | IPromise InvokeAsync(Commands cmd, Func<IPromise> action, Action<IPromise, IDeferred> chain) { | |
| @@ -135,40 +223,20 namespace Implab.Components { | |||||
| 135 |
|
223 | |||
| 136 | var task = new ActionChainTask(action, null, null, true); |
|
224 | var task = new ActionChainTask(action, null, null, true); | |
| 137 |
|
225 | |||
| 138 | lock (m_stateMachine) { |
|
226 | Action<Exception> errorOrCancel = e => { | |
| 139 |
|
|
227 | if (e == null) | |
| 140 |
|
228 | e = new OperationCanceledException(); | ||
| 141 | prev = m_pending; |
|
229 | MoveIfPending(Commands.Fail, null, e, promise); | |
|
|
230 | throw new PromiseTransientException(e); | |||
|
|
231 | }; | |||
| 142 |
|
232 | |||
| 143 | Action<Exception> errorOrCancel = e => { |
|
233 | promise = task.Then( | |
| 144 | if (e == null) |
|
234 | () => MoveIfPending(Commands.Ok, null, null, promise), | |
| 145 | e = new OperationCanceledException(); |
|
235 | errorOrCancel, | |
| 146 |
|
|
236 | errorOrCancel | |
| 147 | lock (m_stateMachine) { |
|
237 | ); | |
| 148 | if (m_pending == promise) { |
|
|||
| 149 | Move(Commands.Fail); |
|
|||
| 150 | m_pending = null; |
|
|||
| 151 | m_lastError = e; |
|
|||
| 152 | } |
|
|||
| 153 | } |
|
|||
| 154 | throw new PromiseTransientException(e); |
|
|||
| 155 | }; |
|
|||
| 156 |
|
238 | |||
| 157 | promise = task.Then( |
|
239 | prev = Move(cmd, promise, null); | |
| 158 | () => { |
|
|||
| 159 | lock(m_stateMachine) { |
|
|||
| 160 | if (m_pending == promise) { |
|
|||
| 161 | Move(Commands.Ok); |
|
|||
| 162 | m_pending = null; |
|
|||
| 163 | } |
|
|||
| 164 | } |
|
|||
| 165 | }, |
|
|||
| 166 | errorOrCancel, |
|
|||
| 167 | errorOrCancel |
|
|||
| 168 | ); |
|
|||
| 169 |
|
||||
| 170 | m_pending = promise; |
|
|||
| 171 | } |
|
|||
| 172 |
|
240 | |||
| 173 | if (prev == null) |
|
241 | if (prev == null) | |
| 174 | task.Resolve(); |
|
242 | task.Resolve(); | |
| @@ -181,8 +249,16 namespace Implab.Components { | |||||
| 181 |
|
249 | |||
| 182 | #region IInitializable implementation |
|
250 | #region IInitializable implementation | |
| 183 |
|
251 | |||
| 184 | public void Init() { |
|
252 | public void Initialize() { | |
| 185 |
|
|
253 | Move(Commands.Init, null, null); | |
|
|
254 | ||||
|
|
255 | try { | |||
|
|
256 | OnInitialize(); | |||
|
|
257 | Move(Commands.Ok, null, null); | |||
|
|
258 | } catch (Exception err) { | |||
|
|
259 | Move(Commands.Fail, null, err); | |||
|
|
260 | throw; | |||
|
|
261 | } | |||
| 186 | } |
|
262 | } | |
| 187 |
|
263 | |||
| 188 | protected virtual void OnInitialize() { |
|
264 | protected virtual void OnInitialize() { | |
| @@ -197,15 +273,16 namespace Implab.Components { | |||||
| 197 | } |
|
273 | } | |
| 198 |
|
274 | |||
| 199 | protected virtual IPromise OnStart() { |
|
275 | protected virtual IPromise OnStart() { | |
| 200 |
return Promise.S |
|
276 | return Promise.Success; | |
| 201 | } |
|
277 | } | |
| 202 |
|
278 | |||
| 203 | public IPromise Stop() { |
|
279 | public IPromise Stop() { | |
| 204 |
|
|
280 | var pending = InvokeAsync(Commands.Stop, OnStop, StopPending); | |
|
|
281 | return m_reusable ? pending : pending.Then(Dispose); | |||
| 205 | } |
|
282 | } | |
| 206 |
|
283 | |||
| 207 | protected virtual IPromise OnStop() { |
|
284 | protected virtual IPromise OnStop() { | |
| 208 |
return Promise.S |
|
285 | return Promise.Success; | |
| 209 | } |
|
286 | } | |
| 210 |
|
287 | |||
| 211 | /// <summary> |
|
288 | /// <summary> | |
| @@ -258,17 +335,14 namespace Implab.Components { | |||||
| 258 | /// </para></remarks> |
|
335 | /// </para></remarks> | |
| 259 | public void Dispose() { |
|
336 | public void Dispose() { | |
| 260 | IPromise pending; |
|
337 | IPromise pending; | |
|
|
338 | ||||
| 261 | lock (m_stateMachine) { |
|
339 | lock (m_stateMachine) { | |
| 262 | if (m_stateMachine.State == ExecutionState.Disposed) |
|
340 | if (m_stateMachine.State == ExecutionState.Disposed) | |
| 263 | return; |
|
341 | return; | |
| 264 |
|
342 | pending = Move(Commands.Dispose, null, null); | ||
| 265 | Move(Commands.Dispose); |
|
343 | } | |
| 266 |
|
344 | |||
| 267 |
|
|
345 | GC.SuppressFinalize(this); | |
| 268 |
|
||||
| 269 | pending = m_pending; |
|
|||
| 270 | m_pending = null; |
|
|||
| 271 | } |
|
|||
| 272 | if (pending != null) { |
|
346 | if (pending != null) { | |
| 273 | pending.Cancel(); |
|
347 | pending.Cancel(); | |
| 274 | pending.Timeout(DisposeTimeout).On( |
|
348 | pending.Timeout(DisposeTimeout).On( | |
| @@ -277,7 +351,7 namespace Implab.Components { | |||||
| 277 | reason => Dispose(true, new OperationCanceledException("The operation is cancelled", reason)) |
|
351 | reason => Dispose(true, new OperationCanceledException("The operation is cancelled", reason)) | |
| 278 | ); |
|
352 | ); | |
| 279 | } else { |
|
353 | } else { | |
| 280 |
Dispose(true, |
|
354 | Dispose(true, null); | |
| 281 | } |
|
355 | } | |
| 282 | } |
|
356 | } | |
| 283 |
|
357 | |||
| @@ -287,6 +361,11 namespace Implab.Components { | |||||
| 287 |
|
361 | |||
| 288 | #endregion |
|
362 | #endregion | |
| 289 |
|
363 | |||
|
|
364 | /// <summary> | |||
|
|
365 | /// Releases all resources used by the component, called automatically, override this method to implement your cleanup. | |||
|
|
366 | /// </summary> | |||
|
|
367 | /// <param name="disposing">true if this method is called during normal dispose process.</param> | |||
|
|
368 | /// <param name="lastError">The last error which occured during the component stop.</param> | |||
| 290 | protected virtual void Dispose(bool disposing, Exception lastError) { |
|
369 | protected virtual void Dispose(bool disposing, Exception lastError) { | |
| 291 |
|
370 | |||
| 292 | } |
|
371 | } | |
| @@ -5,6 +5,7 using System.Text; | |||||
| 5 | namespace Implab.Diagnostics { |
|
5 | namespace Implab.Diagnostics { | |
| 6 | public class TextFileListener: ListenerBase { |
|
6 | public class TextFileListener: ListenerBase { | |
| 7 | readonly TextWriter m_textWriter; |
|
7 | readonly TextWriter m_textWriter; | |
|
|
8 | readonly object m_lock = new object(); | |||
| 8 |
|
9 | |||
| 9 | public TextFileListener(string fileName) { |
|
10 | public TextFileListener(string fileName) { | |
| 10 | m_textWriter = File.CreateText(fileName); |
|
11 | m_textWriter = File.CreateText(fileName); | |
| @@ -20,7 +21,7 namespace Implab.Diagnostics { | |||||
| 20 | msg.Append(" "); |
|
21 | msg.Append(" "); | |
| 21 | msg.AppendFormat("[{0}]:{1}: {2}", args.ThreadId, args.Channel, entry); |
|
22 | msg.AppendFormat("[{0}]:{1}: {2}", args.ThreadId, args.Channel, entry); | |
| 22 |
|
23 | |||
| 23 |
lock (m_ |
|
24 | lock (m_lock) { | |
| 24 | if (!IsDisposed) { |
|
25 | if (!IsDisposed) { | |
| 25 | // тут гарантировано еще не освобожден m_textWriter |
|
26 | // тут гарантировано еще не освобожден m_textWriter | |
| 26 | m_textWriter.WriteLine(msg); |
|
27 | m_textWriter.WriteLine(msg); | |
| @@ -35,7 +36,7 namespace Implab.Diagnostics { | |||||
| 35 | base.Dispose(disposing); |
|
36 | base.Dispose(disposing); | |
| 36 | if (disposing) { |
|
37 | if (disposing) { | |
| 37 | // IsDisposed = true |
|
38 | // IsDisposed = true | |
| 38 |
lock (m_ |
|
39 | lock (m_lock) { | |
| 39 | Safe.Dispose(m_textWriter); |
|
40 | Safe.Dispose(m_textWriter); | |
| 40 | } |
|
41 | } | |
| 41 | } |
|
42 | } | |
| @@ -75,6 +75,7 | |||||
| 75 | <Reference Include="mscorlib" /> |
|
75 | <Reference Include="mscorlib" /> | |
| 76 | </ItemGroup> |
|
76 | </ItemGroup> | |
| 77 | <ItemGroup> |
|
77 | <ItemGroup> | |
|
|
78 | <Compile Include="Components\StateChangeEventArgs.cs" /> | |||
| 78 | <Compile Include="CustomEqualityComparer.cs" /> |
|
79 | <Compile Include="CustomEqualityComparer.cs" /> | |
| 79 | <Compile Include="Diagnostics\ConsoleTraceListener.cs" /> |
|
80 | <Compile Include="Diagnostics\ConsoleTraceListener.cs" /> | |
| 80 | <Compile Include="Diagnostics\LogChannel.cs" /> |
|
81 | <Compile Include="Diagnostics\LogChannel.cs" /> | |
| @@ -269,10 +270,5 | |||||
| 269 | </Properties> |
|
270 | </Properties> | |
| 270 | </MonoDevelop> |
|
271 | </MonoDevelop> | |
| 271 | </ProjectExtensions> |
|
272 | </ProjectExtensions> | |
| 272 | <ItemGroup> |
|
273 | <ItemGroup /> | |
| 273 | <Folder Include="Components\" /> |
|
|||
| 274 | <Folder Include="Automaton\RegularExpressions\" /> |
|
|||
| 275 | <Folder Include="Formats\" /> |
|
|||
| 276 | <Folder Include="Formats\JSON\" /> |
|
|||
| 277 | </ItemGroup> |
|
|||
| 278 | </Project> No newline at end of file |
|
274 | </Project> | |
| @@ -3,11 +3,10 using Implab.Parallels; | |||||
| 3 |
|
3 | |||
| 4 | namespace Implab { |
|
4 | namespace Implab { | |
| 5 | public class Promise : AbstractPromise, IDeferred { |
|
5 | public class Promise : AbstractPromise, IDeferred { | |
| 6 |
public static readonly Promise S |
|
6 | public static readonly IPromise Success; | |
| 7 |
|
7 | |||
| 8 | static Promise() { |
|
8 | static Promise() { | |
| 9 |
S |
|
9 | Success = new SuccessPromise(); | |
| 10 | SUCCESS.Resolve(); |
|
|||
| 11 | } |
|
10 | } | |
| 12 |
|
11 | |||
| 13 | public void Resolve() { |
|
12 | public void Resolve() { | |
| @@ -16,7 +15,11 namespace Implab { | |||||
| 16 |
|
15 | |||
| 17 | public void Reject(Exception error) { |
|
16 | public void Reject(Exception error) { | |
| 18 | SetError(error); |
|
17 | SetError(error); | |
| 19 | } |
|
18 | } | |
|
|
19 | ||||
|
|
20 | public static IPromise FromException(Exception exception) { | |||
|
|
21 | return new FailedPromise(exception); | |||
|
|
22 | } | |||
| 20 | } |
|
23 | } | |
| 21 | } |
|
24 | } | |
| 22 |
|
25 | |||
| @@ -2,7 +2,8 | |||||
| 2 | using System; |
|
2 | using System; | |
| 3 | using Implab.Diagnostics; |
|
3 | using Implab.Diagnostics; | |
| 4 | using System.Collections.Generic; |
|
4 | using System.Collections.Generic; | |
| 5 |
|
5 | using System.Linq; | ||
|
|
6 | ||||
| 6 | namespace Implab { |
|
7 | namespace Implab { | |
| 7 | public static class PromiseExtensions { |
|
8 | public static class PromiseExtensions { | |
| 8 | public static IPromise<T> DispatchToCurrentContext<T>(this IPromise<T> that) { |
|
9 | public static IPromise<T> DispatchToCurrentContext<T>(this IPromise<T> that) { | |
| @@ -75,7 +76,7 namespace Implab { | |||||
| 75 | ((ICancellable)cookie).Cancel(new TimeoutException()); |
|
76 | ((ICancellable)cookie).Cancel(new TimeoutException()); | |
| 76 | } |
|
77 | } | |
| 77 |
|
78 | |||
| 78 |
|
|
79 | /// <summary> | |
| 79 | /// Cancells promise after the specified timeout is elapsed. |
|
80 | /// Cancells promise after the specified timeout is elapsed. | |
| 80 | /// </summary> |
|
81 | /// </summary> | |
| 81 | /// <param name="that">The promise to cancel on timeout.</param> |
|
82 | /// <param name="that">The promise to cancel on timeout.</param> | |
| @@ -88,7 +89,17 namespace Implab { | |||||
| 88 | return that; |
|
89 | return that; | |
| 89 | } |
|
90 | } | |
| 90 |
|
91 | |||
| 91 |
public static IPromise |
|
92 | public static IPromise PromiseAll(this IEnumerable<IPromise> that) { | |
|
|
93 | Safe.ArgumentNotNull(that, "that"); | |||
|
|
94 | return PromiseAll(that.ToList()); | |||
|
|
95 | } | |||
|
|
96 | ||||
|
|
97 | public static IPromise<T[]> PromiseAll<T>(this IEnumerable<IPromise<T>> that) { | |||
|
|
98 | Safe.ArgumentNotNull(that, "that"); | |||
|
|
99 | return PromiseAll(that.ToList()); | |||
|
|
100 | } | |||
|
|
101 | ||||
|
|
102 | public static IPromise PromiseAll(this ICollection<IPromise> that) { | |||
| 92 | Safe.ArgumentNotNull(that, "that"); |
|
103 | Safe.ArgumentNotNull(that, "that"); | |
| 93 |
|
104 | |||
| 94 | int count = that.Count; |
|
105 | int count = that.Count; | |
| @@ -128,7 +139,7 namespace Implab { | |||||
| 128 | return medium; |
|
139 | return medium; | |
| 129 | } |
|
140 | } | |
| 130 |
|
141 | |||
| 131 |
public static IPromise<T[]> |
|
142 | public static IPromise<T[]> PromiseAll<T>(this ICollection<IPromise<T>> that) { | |
| 132 | Safe.ArgumentNotNull(that, "that"); |
|
143 | Safe.ArgumentNotNull(that, "that"); | |
| 133 |
|
144 | |||
| 134 | int count = that.Count; |
|
145 | int count = that.Count; | |
General Comments 3
ok, latest stable version should be in default
You need to be logged in to leave comments.
Login now
