##// 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 336 Console.WriteLine("done reader #2: {0} ms", Environment.TickCount - t1);
337 337 }
338 338 )
339 .Bundle()
339 .PromiseAll()
340 340 .Join();
341 341
342 342 Assert.AreEqual(count * 3, res1 + res2);
@@ -414,7 +414,7 namespace Implab.Test {
414 414 Console.WriteLine("done reader #2: {0} ms", Environment.TickCount - t1);
415 415 }
416 416 )
417 .Bundle()
417 .PromiseAll()
418 418 .Join();
419 419
420 420 Assert.AreEqual(summ , r1 + r2);
@@ -490,7 +490,7 namespace Implab.Test {
490 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 494 .Join();
495 495
496 496 Assert.AreEqual(summ , r1 + r2);
@@ -593,7 +593,7 namespace Implab.Test {
593 593 Console.WriteLine("done reader #2: {0} ms, {1} items", Environment.TickCount - t1, count);
594 594 }
595 595 )
596 .Bundle()
596 .PromiseAll()
597 597 .Join();
598 598
599 599 Assert.AreEqual(summ , r1 + r2);
@@ -835,7 +835,7 namespace Implab.Test {
835 835 log.Enqueue("Writer #1 lock released");
836 836 }
837 837 }
838 ).Bundle().Join(1000);
838 ).PromiseAll().Join(1000);
839 839 log.Enqueue("Done");
840 840 } catch(Exception error) {
841 841 log.Enqueue(error.Message);
@@ -1,52 +1,55
1 <?xml version="1.0" encoding="utf-8"?>
2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <PropertyGroup>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6 <ProductVersion>8.0.30703</ProductVersion>
7 <SchemaVersion>2.0</SchemaVersion>
8 <ProjectGuid>{4D364996-7ECD-4193-8F90-F223FFEA49DA}</ProjectGuid>
9 <OutputType>Library</OutputType>
10 <RootNamespace>Implab.Format.Test</RootNamespace>
11 <AssemblyName>Implab.Format.Test</AssemblyName>
12 <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
13 <ReleaseVersion>0.2</ReleaseVersion>
14 </PropertyGroup>
15 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
16 <DebugSymbols>true</DebugSymbols>
17 <DebugType>full</DebugType>
18 <Optimize>false</Optimize>
19 <OutputPath>bin\Debug</OutputPath>
20 <DefineConstants>DEBUG;</DefineConstants>
21 <ErrorReport>prompt</ErrorReport>
22 <WarningLevel>4</WarningLevel>
23 <ConsolePause>false</ConsolePause>
24 </PropertyGroup>
25 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
26 <DebugType>full</DebugType>
27 <Optimize>true</Optimize>
28 <OutputPath>bin\Release</OutputPath>
29 <ErrorReport>prompt</ErrorReport>
30 <WarningLevel>4</WarningLevel>
31 <ConsolePause>false</ConsolePause>
32 </PropertyGroup>
33 <ItemGroup>
34 <Reference Include="System" />
35 <Reference Include="nunit.framework">
36 <HintPath>..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
37 </Reference>
38 </ItemGroup>
39 <ItemGroup>
40 <Compile Include="JsonTests.cs" />
41 </ItemGroup>
42 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
43 <ItemGroup>
44 <ProjectReference Include="..\..\Implab\Implab.csproj">
45 <Project>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</Project>
46 <Name>Implab</Name>
47 </ProjectReference>
48 </ItemGroup>
49 <ItemGroup>
50 <None Include="packages.config" />
51 </ItemGroup>
1 <?xml version="1.0" encoding="utf-8"?>
2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <PropertyGroup>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6 <ProductVersion>8.0.30703</ProductVersion>
7 <SchemaVersion>2.0</SchemaVersion>
8 <ProjectGuid>{4D364996-7ECD-4193-8F90-F223FFEA49DA}</ProjectGuid>
9 <OutputType>Library</OutputType>
10 <RootNamespace>Implab.Format.Test</RootNamespace>
11 <AssemblyName>Implab.Format.Test</AssemblyName>
12 <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
13 <ReleaseVersion>0.2</ReleaseVersion>
14 </PropertyGroup>
15 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
16 <DebugSymbols>true</DebugSymbols>
17 <DebugType>full</DebugType>
18 <Optimize>false</Optimize>
19 <OutputPath>bin\Debug</OutputPath>
20 <DefineConstants>DEBUG;</DefineConstants>
21 <ErrorReport>prompt</ErrorReport>
22 <WarningLevel>4</WarningLevel>
23 <ConsolePause>false</ConsolePause>
24 </PropertyGroup>
25 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
26 <DebugType>full</DebugType>
27 <Optimize>true</Optimize>
28 <OutputPath>bin\Release</OutputPath>
29 <ErrorReport>prompt</ErrorReport>
30 <WarningLevel>4</WarningLevel>
31 <ConsolePause>false</ConsolePause>
32 </PropertyGroup>
33 <ItemGroup>
34 <Reference Include="System" />
35 <Reference Include="nunit.framework">
36 <HintPath>..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
37 </Reference>
38 </ItemGroup>
39 <ItemGroup>
40 <Compile Include="JsonTests.cs" />
41 </ItemGroup>
42 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
43 <ItemGroup>
44 <ProjectReference Include="..\..\Implab\Implab.csproj">
45 <Project>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</Project>
46 <Name>Implab</Name>
47 </ProjectReference>
48 </ItemGroup>
49 <ItemGroup>
50 <None Include="packages.config" />
51 </ItemGroup>
52 <ItemGroup>
53 <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
54 </ItemGroup>
52 55 </Project> No newline at end of file
@@ -1,75 +1,81
1 <?xml version="1.0" encoding="utf-8"?>
2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <PropertyGroup>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6 <ProductVersion>8.0.30703</ProductVersion>
7 <SchemaVersion>2.0</SchemaVersion>
8 <ProjectGuid>{2BD05F84-E067-4B87-9477-FDC2676A21C6}</ProjectGuid>
9 <OutputType>Library</OutputType>
10 <RootNamespace>Implab.Test</RootNamespace>
11 <AssemblyName>Implab.Test</AssemblyName>
12 <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
13 <ReleaseVersion>0.2</ReleaseVersion>
14 </PropertyGroup>
15 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
16 <DebugSymbols>true</DebugSymbols>
17 <DebugType>full</DebugType>
18 <Optimize>false</Optimize>
19 <OutputPath>bin\Debug</OutputPath>
20 <DefineConstants>DEBUG;MONO</DefineConstants>
21 <ErrorReport>prompt</ErrorReport>
22 <WarningLevel>4</WarningLevel>
23 <ConsolePause>false</ConsolePause>
24 </PropertyGroup>
25 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
26 <Optimize>true</Optimize>
27 <OutputPath>bin\Release</OutputPath>
28 <ErrorReport>prompt</ErrorReport>
29 <WarningLevel>4</WarningLevel>
30 <ConsolePause>false</ConsolePause>
31 <DefineConstants>MONO</DefineConstants>
32 </PropertyGroup>
33 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' ">
34 <DebugSymbols>true</DebugSymbols>
35 <DebugType>full</DebugType>
36 <Optimize>false</Optimize>
37 <OutputPath>bin\Debug</OutputPath>
38 <DefineConstants>DEBUG;TRACE;NET_4_5;MONO</DefineConstants>
39 <ErrorReport>prompt</ErrorReport>
40 <WarningLevel>4</WarningLevel>
41 <ConsolePause>false</ConsolePause>
42 </PropertyGroup>
43 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' ">
44 <Optimize>true</Optimize>
45 <OutputPath>bin\Release</OutputPath>
46 <DefineConstants>NET_4_5;MONO</DefineConstants>
47 <ErrorReport>prompt</ErrorReport>
48 <WarningLevel>4</WarningLevel>
49 <ConsolePause>false</ConsolePause>
50 </PropertyGroup>
51 <ItemGroup>
52 <Reference Include="System" />
53 <Reference Include="nunit.framework" />
54 </ItemGroup>
55 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
56 <ItemGroup>
57 <Compile Include="AsyncTests.cs" />
58 <Compile Include="PromiseHelper.cs" />
59 <Compile Include="Properties\AssemblyInfo.cs" />
60 <Compile Include="CancelationTests.cs" />
61 <Compile Include="RunnableComponentTests.cs" />
62 <Compile Include="PollingComponentTests.cs" />
63 <Compile Include="Mock\MockRunnableComponent.cs" />
64 <Compile Include="Mock\MockPollingComponent.cs" />
65 </ItemGroup>
66 <ItemGroup>
67 <ProjectReference Include="..\Implab\Implab.csproj">
68 <Project>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</Project>
69 <Name>Implab</Name>
70 </ProjectReference>
71 </ItemGroup>
72 <ItemGroup>
73 <Folder Include="Mock\" />
74 </ItemGroup>
1 <?xml version="1.0" encoding="utf-8"?>
2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <PropertyGroup>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6 <ProductVersion>8.0.30703</ProductVersion>
7 <SchemaVersion>2.0</SchemaVersion>
8 <ProjectGuid>{2BD05F84-E067-4B87-9477-FDC2676A21C6}</ProjectGuid>
9 <OutputType>Library</OutputType>
10 <RootNamespace>Implab.Test</RootNamespace>
11 <AssemblyName>Implab.Test</AssemblyName>
12 <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
13 <ReleaseVersion>0.2</ReleaseVersion>
14 </PropertyGroup>
15 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
16 <DebugSymbols>true</DebugSymbols>
17 <DebugType>full</DebugType>
18 <Optimize>false</Optimize>
19 <OutputPath>bin\Debug</OutputPath>
20 <DefineConstants>DEBUG;MONO</DefineConstants>
21 <ErrorReport>prompt</ErrorReport>
22 <WarningLevel>4</WarningLevel>
23 <ConsolePause>false</ConsolePause>
24 </PropertyGroup>
25 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
26 <Optimize>true</Optimize>
27 <OutputPath>bin\Release</OutputPath>
28 <ErrorReport>prompt</ErrorReport>
29 <WarningLevel>4</WarningLevel>
30 <ConsolePause>false</ConsolePause>
31 <DefineConstants>MONO</DefineConstants>
32 </PropertyGroup>
33 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' ">
34 <DebugSymbols>true</DebugSymbols>
35 <DebugType>full</DebugType>
36 <Optimize>false</Optimize>
37 <OutputPath>bin\Debug</OutputPath>
38 <DefineConstants>DEBUG;TRACE;NET_4_5;MONO</DefineConstants>
39 <ErrorReport>prompt</ErrorReport>
40 <WarningLevel>4</WarningLevel>
41 <ConsolePause>false</ConsolePause>
42 </PropertyGroup>
43 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' ">
44 <Optimize>true</Optimize>
45 <OutputPath>bin\Release</OutputPath>
46 <DefineConstants>NET_4_5;MONO</DefineConstants>
47 <ErrorReport>prompt</ErrorReport>
48 <WarningLevel>4</WarningLevel>
49 <ConsolePause>false</ConsolePause>
50 </PropertyGroup>
51 <ItemGroup>
52 <Reference Include="nunit.framework, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
53 <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
54 <Private>True</Private>
55 </Reference>
56 <Reference Include="System" />
57 </ItemGroup>
58 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
59 <ItemGroup>
60 <Compile Include="AsyncTests.cs" />
61 <Compile Include="PromiseHelper.cs" />
62 <Compile Include="Properties\AssemblyInfo.cs" />
63 <Compile Include="CancelationTests.cs" />
64 <Compile Include="RunnableComponentTests.cs" />
65 <Compile Include="PollingComponentTests.cs" />
66 <Compile Include="Mock\MockRunnableComponent.cs" />
67 <Compile Include="Mock\MockPollingComponent.cs" />
68 </ItemGroup>
69 <ItemGroup>
70 <ProjectReference Include="..\Implab\Implab.csproj">
71 <Project>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</Project>
72 <Name>Implab</Name>
73 </ProjectReference>
74 </ItemGroup>
75 <ItemGroup>
76 <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
77 </ItemGroup>
78 <ItemGroup>
79 <None Include="packages.config" />
80 </ItemGroup>
75 81 </Project> No newline at end of file
@@ -50,7 +50,7 namespace Implab.Test.Mock {
50 50 }
51 51
52 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 56 protected override void OnTickCancel(Exception error) {
@@ -6,6 +6,9 namespace Implab.Test.Mock {
6 6 public MockRunnableComponent(bool initialized) : base(initialized) {
7 7 }
8 8
9 public MockRunnableComponent(bool initialized, bool reusable) : base(initialized, reusable) {
10 }
11
9 12 public Action MockInit {
10 13 get;
11 14 set;
@@ -21,6 +24,11 namespace Implab.Test.Mock {
21 24 set;
22 25 }
23 26
27 public Action<bool, Exception> MockDispose {
28 get;
29 set;
30 }
31
24 32 protected override IPromise OnStart() {
25 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 41 if (MockInit != null)
34 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 37 Assert.AreEqual(ExecutionState.Created, comp.State);
38 38
39 comp.Init();
39 comp.Initialize();
40 40
41 41 Assert.AreEqual(ExecutionState.Ready, comp.State);
42 42
@@ -57,7 +57,7 namespace Implab.Test {
57 57 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
58 58 comp.MockTick = ct => {
59 59 signal.Set();
60 return Promise.SUCCESS;
60 return Promise.Success;
61 61 };
62 62
63 63 comp.Start().Join(1000);
@@ -39,7 +39,7 namespace Implab.Test {
39 39
40 40 Assert.AreEqual(ExecutionState.Created, comp.State);
41 41
42 comp.Init();
42 comp.Initialize();
43 43
44 44 Assert.AreEqual(ExecutionState.Ready, comp.State);
45 45
@@ -65,7 +65,7 namespace Implab.Test {
65 65 ShouldThrow(() => comp.Stop());
66 66 Assert.AreEqual(ExecutionState.Created, comp.State);
67 67
68 ShouldThrow(comp.Init);
68 ShouldThrow(comp.Initialize);
69 69
70 70 Assert.AreEqual(ExecutionState.Failed, comp.State);
71 71
@@ -85,12 +85,77 namespace Implab.Test {
85 85
86 86 ShouldThrow(() => comp.Start());
87 87 ShouldThrow(() => comp.Stop());
88 ShouldThrow(comp.Init);
88 ShouldThrow(comp.Initialize);
89 89
90 90 Assert.AreEqual(ExecutionState.Disposed, comp.State);
91 91 }
92 92
93 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 159 public void StartCancelTest() {
95 160 var comp = new MockRunnableComponent(true) {
96 161 MockStart = () => PromiseHelper.Sleep(100000, 0)
@@ -28,6 +28,14 namespace Implab.Automaton {
28 28 public override int GetHashCode() {
29 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 3 namespace Implab.Components {
4 4 /// <summary>
5 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
7 /// to complete the initialization must be passed before the calling <see cref="Init()"/>
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="Initialize()"/>
8 8 /// </summary>
9 9 public interface IInitializable {
10 10 /// <summary>
@@ -12,10 +12,10 namespace Implab.Components {
12 12 /// </summary>
13 13 /// <remarks>
14 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 16 /// of components where cyclic references may take place.
17 17 /// </remarks>
18 void Init();
18 void Initialize();
19 19 }
20 20 }
21 21
@@ -14,6 +14,8 namespace Implab.Components {
14 14
15 15 ExecutionState State { get; }
16 16
17 event EventHandler<StateChangeEventArgs> StateChanged;
18
17 19 Exception LastError { get; }
18 20 }
19 21 }
@@ -124,7 +124,7 namespace Implab.Components {
124 124 /// Invoked when the timer ticks, use this method to implement your logic
125 125 /// </summary>
126 126 protected virtual IPromise OnTick(ICancellationToken cancellationToken) {
127 return Promise.SUCCESS;
127 return Promise.Success;
128 128 }
129 129
130 130 protected override IPromise OnStop() {
@@ -9,7 +9,8 namespace Implab.Components {
9 9 Start,
10 10 Stop,
11 11 Dispose,
12 Last = Dispose
12 Reset,
13 Last = Reset
13 14 }
14 15
15 16 class StateMachine {
@@ -37,9 +38,11 namespace Implab.Components {
37 38 Edge(ExecutionState.Running, ExecutionState.Disposed, Commands.Dispose);
38 39
39 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 44 Edge(ExecutionState.Failed, ExecutionState.Disposed, Commands.Dispose);
45 Edge(ExecutionState.Failed, ExecutionState.Initializing, Commands.Reset);
43 46 }
44 47
45 48 static void Edge(ExecutionState s1, ExecutionState s2, Commands cmd) {
@@ -67,11 +70,26 namespace Implab.Components {
67 70 IPromise m_pending;
68 71 Exception m_lastError;
69 72
70 readonly StateMachine m_stateMachine;
71
72 protected RunnableComponent(bool initialized) {
73 readonly StateMachine m_stateMachine;
74 readonly bool m_reusable;
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 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 95 /// <summary>
@@ -84,49 +102,119 namespace Implab.Components {
84 102
85 103 void ThrowInvalidCommand(Commands cmd) {
86 104 if (m_stateMachine.State == ExecutionState.Disposed)
87 throw new ObjectDisposedException(ToString());
88
89 throw new InvalidOperationException(String.Format("Commnd {0} is not allowed in the state {1}", cmd, m_stateMachine.State));
105 throw new ObjectDisposedException(ToString());
106
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) {
93 if (!m_stateMachine.Move(cmd))
94 ThrowInvalidCommand(cmd);
129 bool MoveIfPending(Commands cmd, IPromise pending, Exception error, IPromise expected) {
130 ExecutionState prev, current;
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 174 /// <summary>
98 175 /// Moves the component from running to failed state.
99 176 /// </summary>
100 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.
102 /// This method works only for the running state, in any other state it will return false.</returns>
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;
178 protected bool Fail(Exception error) {
179 return MoveIfInState(Commands.Fail, null, error, ExecutionState.Running);
112 180 }
113 181
114 void Invoke(Commands cmd, Action action) {
115 lock (m_stateMachine)
116 Move(cmd);
117
182 /// <summary>
183 /// Tries to reset <see cref="ExecutionState.Failed"/> state to <see cref="ExecutionState.Ready"/>.
184 /// </summary>
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 198 try {
119 action();
120 lock(m_stateMachine)
121 Move(Commands.Ok);
122
199 OnResetState();
200 Move(Commands.Ok, null, null);
201 return true;
123 202 } catch (Exception err) {
124 lock (m_stateMachine) {
125 Move(Commands.Fail);
126 m_lastError = err;
127 }
203 Move(Commands.Fail, null, err);
128 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 220 IPromise InvokeAsync(Commands cmd, Func<IPromise> action, Action<IPromise, IDeferred> chain) {
@@ -135,40 +223,20 namespace Implab.Components {
135 223
136 224 var task = new ActionChainTask(action, null, null, true);
137 225
138 lock (m_stateMachine) {
139 Move(cmd);
140
141 prev = m_pending;
226 Action<Exception> errorOrCancel = e => {
227 if (e == null)
228 e = new OperationCanceledException();
229 MoveIfPending(Commands.Fail, null, e, promise);
230 throw new PromiseTransientException(e);
231 };
142 232
143 Action<Exception> errorOrCancel = e => {
144 if (e == null)
145 e = new OperationCanceledException();
146
147 lock (m_stateMachine) {
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 };
233 promise = task.Then(
234 () => MoveIfPending(Commands.Ok, null, null, promise),
235 errorOrCancel,
236 errorOrCancel
237 );
156 238
157 promise = task.Then(
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 }
239 prev = Move(cmd, promise, null);
172 240
173 241 if (prev == null)
174 242 task.Resolve();
@@ -181,8 +249,16 namespace Implab.Components {
181 249
182 250 #region IInitializable implementation
183 251
184 public void Init() {
185 Invoke(Commands.Init, OnInitialize);
252 public void Initialize() {
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 264 protected virtual void OnInitialize() {
@@ -197,15 +273,16 namespace Implab.Components {
197 273 }
198 274
199 275 protected virtual IPromise OnStart() {
200 return Promise.SUCCESS;
276 return Promise.Success;
201 277 }
202 278
203 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 284 protected virtual IPromise OnStop() {
208 return Promise.SUCCESS;
285 return Promise.Success;
209 286 }
210 287
211 288 /// <summary>
@@ -258,17 +335,14 namespace Implab.Components {
258 335 /// </para></remarks>
259 336 public void Dispose() {
260 337 IPromise pending;
338
261 339 lock (m_stateMachine) {
262 340 if (m_stateMachine.State == ExecutionState.Disposed)
263 341 return;
264
265 Move(Commands.Dispose);
342 pending = Move(Commands.Dispose, null, null);
343 }
266 344
267 GC.SuppressFinalize(this);
268
269 pending = m_pending;
270 m_pending = null;
271 }
345 GC.SuppressFinalize(this);
272 346 if (pending != null) {
273 347 pending.Cancel();
274 348 pending.Timeout(DisposeTimeout).On(
@@ -277,7 +351,7 namespace Implab.Components {
277 351 reason => Dispose(true, new OperationCanceledException("The operation is cancelled", reason))
278 352 );
279 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 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 369 protected virtual void Dispose(bool disposing, Exception lastError) {
291 370
292 371 }
@@ -5,6 +5,7 using System.Text;
5 5 namespace Implab.Diagnostics {
6 6 public class TextFileListener: ListenerBase {
7 7 readonly TextWriter m_textWriter;
8 readonly object m_lock = new object();
8 9
9 10 public TextFileListener(string fileName) {
10 11 m_textWriter = File.CreateText(fileName);
@@ -20,7 +21,7 namespace Implab.Diagnostics {
20 21 msg.Append(" ");
21 22 msg.AppendFormat("[{0}]:{1}: {2}", args.ThreadId, args.Channel, entry);
22 23
23 lock (m_textWriter) {
24 lock (m_lock) {
24 25 if (!IsDisposed) {
25 26 // тут гарантировано еще не освобожден m_textWriter
26 27 m_textWriter.WriteLine(msg);
@@ -35,7 +36,7 namespace Implab.Diagnostics {
35 36 base.Dispose(disposing);
36 37 if (disposing) {
37 38 // IsDisposed = true
38 lock (m_textWriter) {
39 lock (m_lock) {
39 40 Safe.Dispose(m_textWriter);
40 41 }
41 42 }
@@ -75,6 +75,7
75 75 <Reference Include="mscorlib" />
76 76 </ItemGroup>
77 77 <ItemGroup>
78 <Compile Include="Components\StateChangeEventArgs.cs" />
78 79 <Compile Include="CustomEqualityComparer.cs" />
79 80 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
80 81 <Compile Include="Diagnostics\LogChannel.cs" />
@@ -269,10 +270,5
269 270 </Properties>
270 271 </MonoDevelop>
271 272 </ProjectExtensions>
272 <ItemGroup>
273 <Folder Include="Components\" />
274 <Folder Include="Automaton\RegularExpressions\" />
275 <Folder Include="Formats\" />
276 <Folder Include="Formats\JSON\" />
277 </ItemGroup>
273 <ItemGroup />
278 274 </Project> No newline at end of file
@@ -3,11 +3,10 using Implab.Parallels;
3 3
4 4 namespace Implab {
5 5 public class Promise : AbstractPromise, IDeferred {
6 public static readonly Promise SUCCESS;
6 public static readonly IPromise Success;
7 7
8 8 static Promise() {
9 SUCCESS = new Promise();
10 SUCCESS.Resolve();
9 Success = new SuccessPromise();
11 10 }
12 11
13 12 public void Resolve() {
@@ -16,7 +15,11 namespace Implab {
16 15
17 16 public void Reject(Exception error) {
18 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 2 using System;
3 3 using Implab.Diagnostics;
4 4 using System.Collections.Generic;
5
5 using System.Linq;
6
6 7 namespace Implab {
7 8 public static class PromiseExtensions {
8 9 public static IPromise<T> DispatchToCurrentContext<T>(this IPromise<T> that) {
@@ -75,7 +76,7 namespace Implab {
75 76 ((ICancellable)cookie).Cancel(new TimeoutException());
76 77 }
77 78
78 /// <summary>
79 /// <summary>
79 80 /// Cancells promise after the specified timeout is elapsed.
80 81 /// </summary>
81 82 /// <param name="that">The promise to cancel on timeout.</param>
@@ -88,7 +89,17 namespace Implab {
88 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 103 Safe.ArgumentNotNull(that, "that");
93 104
94 105 int count = that.Count;
@@ -128,7 +139,7 namespace Implab {
128 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 143 Safe.ArgumentNotNull(that, "that");
133 144
134 145 int count = that.Count;
@@ -83,7 +83,7 namespace Implab
83 83
84 84 try {
85 85 action();
86 return Promise.SUCCESS;
86 return Promise.Success;
87 87 } catch (Exception err) {
88 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