##// END OF EJS Templates
Added ResetState to RunnableComponent to reset in case of failure...
cin -
r205:8200ab154c8a v2
parent child
Show More
@@ -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 .Bundle()
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 .Bundle()
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 .Bundle()
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 .Bundle()
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 ).Bundle().Join(1000);
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="CancelationTests.cs" />
60 <Compile Include="AsyncTests.cs" />
61 <Compile Include="RunnableComponentTests.cs" />
61 <Compile Include="PromiseHelper.cs" />
62 <Compile Include="PollingComponentTests.cs" />
62 <Compile Include="Properties\AssemblyInfo.cs" />
63 <Compile Include="Mock\MockRunnableComponent.cs" />
63 <Compile Include="CancelationTests.cs" />
64 <Compile Include="Mock\MockPollingComponent.cs" />
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.SUCCESS;
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.SUCCESS;
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.SUCCESS;
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 Last = Dispose
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.Disposed, Commands.Ok);
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 action();
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 Move(cmd);
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 Invoke(Commands.Init, OnInitialize);
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.SUCCESS;
276 return Promise.Success;
201 }
277 }
202
278
203 public IPromise Stop() {
279 public IPromise Stop() {
204 return InvokeAsync(Commands.Stop, OnStop, StopPending).Then(Dispose);
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.SUCCESS;
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 GC.SuppressFinalize(this);
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, m_lastError);
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_textWriter) {
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_textWriter) {
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 SUCCESS;
6 public static readonly IPromise Success;
7
7
8 static Promise() {
8 static Promise() {
9 SUCCESS = new Promise();
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 /// <summary>
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 Bundle(this ICollection<IPromise> that) {
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[]> Bundle<T>(this ICollection<IPromise<T>> that) {
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;
@@ -83,7 +83,7 namespace Implab
83
83
84 try {
84 try {
85 action();
85 action();
86 return Promise.SUCCESS;
86 return Promise.Success;
87 } catch (Exception err) {
87 } catch (Exception err) {
88 return new FailedPromise(err);
88 return new FailedPromise(err);
89 }
89 }
General Comments 3
Under Review
author

Auto status change to "Under Review"

Approved
author

ok, latest stable version should be in default

You need to be logged in to leave comments. Login now