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