# HG changeset patch
# User cin
# Date 1523833959 -10800
# Node ID f1696cdc3d7a5a9e19569567722285926c5d61b0
# Parent 05a87f575512417112d37cb158c483d1beeef778
Added IInitializable.Initialize() overload
Added IRunnable.Start(), IRunnable.Start() overloads
Fixed cancellation of the current operation when Stop() is called
More tests
diff -r 05a87f575512 -r f1696cdc3d7a Implab.Format.Test/Implab.Format.Test.csproj
--- a/Implab.Format.Test/Implab.Format.Test.csproj Fri Apr 13 19:15:11 2018 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-
-
-
- Debug
- AnyCPU
- 8.0.30703
- 2.0
- {4D364996-7ECD-4193-8F90-F223FFEA49DA}
- Library
- Implab.Format.Test
- Implab.Format.Test
- v4.5
- 0.2
-
-
- true
- full
- false
- bin\Debug
- DEBUG;
- prompt
- 4
- false
-
-
- full
- true
- bin\Release
- prompt
- 4
- false
-
-
-
- ..\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll
- True
-
-
-
-
-
-
-
-
-
-
- {F550F1F8-8746-4AD0-9614-855F4C4B7F05}
- Implab
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff -r 05a87f575512 -r f1696cdc3d7a Implab.Format.Test/JsonTests.cs
--- a/Implab.Format.Test/JsonTests.cs Fri Apr 13 19:15:11 2018 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,173 +0,0 @@
-using NUnit.Framework;
-using System;
-using Implab.Automaton;
-using Implab.Xml;
-using System.Xml;
-using Implab.Formats;
-using Implab.Formats.Json;
-using System.IO;
-
-namespace Implab.Format.Test {
- [TestFixture]
- public class JsonTests {
-
- [Test]
- public void TestScannerValidTokens() {
- using (var scanner = JsonStringScanner.Create(@"9123, -123, 0, 0.1, -0.2, -0.1e3, 1.3E-3, ""some \t\n\u0020 text"", literal []{}:")) {
-
- Tuple[] expexted = {
- new Tuple(JsonTokenType.Number, "9123"),
- new Tuple(JsonTokenType.ValueSeparator, null),
- new Tuple(JsonTokenType.Number, "-123"),
- new Tuple(JsonTokenType.ValueSeparator, null),
- new Tuple(JsonTokenType.Number, "0"),
- new Tuple(JsonTokenType.ValueSeparator, null),
- new Tuple(JsonTokenType.Number, "0.1"),
- new Tuple(JsonTokenType.ValueSeparator, null),
- new Tuple(JsonTokenType.Number, "-0.2"),
- new Tuple(JsonTokenType.ValueSeparator, null),
- new Tuple(JsonTokenType.Number, "-0.1e3"),
- new Tuple(JsonTokenType.ValueSeparator, null),
- new Tuple(JsonTokenType.Number, "1.3E-3"),
- new Tuple(JsonTokenType.ValueSeparator, null),
- new Tuple(JsonTokenType.String, "some \t\n text"),
- new Tuple(JsonTokenType.ValueSeparator, null),
- new Tuple(JsonTokenType.Literal, "literal"),
- new Tuple(JsonTokenType.BeginArray, null),
- new Tuple(JsonTokenType.EndArray, null),
- new Tuple(JsonTokenType.BeginObject, null),
- new Tuple(JsonTokenType.EndObject, null),
- new Tuple(JsonTokenType.NameSeparator, null)
- };
-
- string value;
- JsonTokenType tokenType;
- for (var i = 0; i < expexted.Length; i++) {
-
- Assert.IsTrue(scanner.ReadToken(out value, out tokenType));
- Assert.AreEqual(expexted[i].Item1, tokenType);
- Assert.AreEqual(expexted[i].Item2, value);
- }
-
- Assert.IsFalse(scanner.ReadToken(out value, out tokenType));
- }
- }
-
- [Test]
- public void TestScannerBadTokens() {
- var bad = new[] {
- " 1",
- " literal",
- " \"",
- "\"unclosed string",
- "1.bad",
- "001", // should be read as three numbers
- "--10",
- "+10",
- "1.0.0",
- "1e1.0",
- "l1teral0",
- ".123",
- "-.123"
- };
-
- foreach (var json in bad) {
- using (var scanner = JsonStringScanner.Create(json)) {
- try {
- string value;
- JsonTokenType token;
- scanner.ReadToken(out value, out token);
- if (!Object.Equals(value, json)) {
- Console.WriteLine("'{0}' is read as {1}", json, value is String ? String.Format("'{0}'", value) : value);
- continue;
- }
- Assert.Fail("Token '{0}' shouldn't pass", json);
- } catch (ParserException e) {
- Console.WriteLine(e.Message);
- }
- }
- }
- }
-
- [Test]
- public void JsonXmlReaderSimpleTest() {
- var json = "\"some text\"";
- //Console.WriteLine($"JSON: {json}");
- //Console.WriteLine("XML");
- /*using (var xmlReader = new JsonXmlReader(new JSONParser(json), new JsonXmlReaderOptions { NamespaceUri = "JsonXmlReaderSimpleTest", RootName = "string", NodesPrefix = "json" })) {
- Assert.AreEqual(xmlReader.ReadState, System.Xml.ReadState.Initial);
-
- AssertRead(xmlReader, XmlNodeType.XmlDeclaration);
- AssertRead(xmlReader, XmlNodeType.Element);
- AssertRead(xmlReader, XmlNodeType.Text);
- AssertRead(xmlReader, XmlNodeType.EndElement);
- Assert.IsFalse(xmlReader.Read());
- }*/
-
- //DumpJsonParse("\"text value\"");
- //DumpJsonParse("null");
- //DumpJsonParse("true");
- //DumpJsonParse("{}");
- //DumpJsonParse("[]");
- DumpJsonParse("{\"one\":1, \"two\":2}");
- DumpJsonParse("[1,\"\",2,3]");
- DumpJsonParse("[{\"info\": [7,8,9]}]");
- DumpJsonFlatParse("[1,2,\"\",[3,4],{\"info\": [5,6]},{\"num\": [7,8,null]}, null,[null]]");
- }
-
- [Test]
- public void JsonBenchmark() {
- var t = Environment.TickCount;
- using (var reader = new JsonXmlReader(JsonReader.Create("e:\\citylots.json"), new JsonXmlReaderOptions { NamespaceUri = "XmlReaderSimpleTest", RootName = "data" })) {
- while (reader.Read()) {
- }
- }
- Console.WriteLine($"JsonXmlReader: {Environment.TickCount - t} ms");
-
- t = Environment.TickCount;
- using(var reader = JsonReader.Create("e:\\citylots.json")) {
- while(reader.Read()) {
- }
- }
-
- Console.WriteLine($"JsonReader: {Environment.TickCount - t} ms");
-
- t = Environment.TickCount;
- using (var reader = XmlReader.Create("file:///e:\\citylots.xml")) {
- while (reader.Read()) {
- }
- }
-
- Console.WriteLine($"XmlReader: {Environment.TickCount - t} ms");
- }
-
- void AssertRead(XmlReader reader, XmlNodeType expected) {
- Assert.IsTrue(reader.Read());
- Console.WriteLine($"{new string(' ', reader.Depth * 2)}{reader}");
- Assert.AreEqual(expected, reader.NodeType);
- }
-
- void DumpJsonParse(string json) {
- Console.WriteLine($"JSON: {json}");
- Console.WriteLine("XML");
- using (var xmlReader = new JsonXmlReader(JsonReader.ParseString(json), new JsonXmlReaderOptions { NamespaceUri = "JsonXmlReaderSimpleTest", NodesPrefix = "json" })) {
- while (xmlReader.Read())
- Console.WriteLine($"{new string(' ', xmlReader.Depth * 2)}{xmlReader}");
- }
- }
-
- void DumpJsonFlatParse(string json) {
- Console.WriteLine($"JSON: {json}");
- Console.WriteLine("XML");
- using (var xmlWriter = XmlWriter.Create(Console.Out, new XmlWriterSettings {
- Indent = true,
- CloseOutput = false,
- ConformanceLevel = ConformanceLevel.Document
- }))
- using (var xmlReader = new JsonXmlReader(JsonReader.ParseString(json), new JsonXmlReaderOptions { NamespaceUri = "JsonXmlReaderSimpleTest", NodesPrefix = "", FlattenArrays = true })) {
- xmlWriter.WriteNode(xmlReader, false);
- }
- }
- }
-}
-
diff -r 05a87f575512 -r f1696cdc3d7a Implab.Format.Test/packages.config
--- a/Implab.Format.Test/packages.config Fri Apr 13 19:15:11 2018 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff -r 05a87f575512 -r f1696cdc3d7a Implab.Test/JsonTests.cs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.Test/JsonTests.cs Mon Apr 16 02:12:39 2018 +0300
@@ -0,0 +1,152 @@
+using Xunit;
+using System;
+using Implab.Automaton;
+using Implab.Xml;
+using System.Xml;
+using Implab.Formats;
+using Implab.Formats.Json;
+using System.IO;
+
+namespace Implab.Test {
+ public class JsonTests {
+
+ [Fact]
+ public void TestScannerValidTokens() {
+ using (var scanner = JsonStringScanner.Create(@"9123, -123, 0, 0.1, -0.2, -0.1e3, 1.3E-3, ""some \t\n\u0020 text"", literal []{}:")) {
+
+ Tuple[] expexted = {
+ new Tuple(JsonTokenType.Number, "9123"),
+ new Tuple(JsonTokenType.ValueSeparator, null),
+ new Tuple(JsonTokenType.Number, "-123"),
+ new Tuple(JsonTokenType.ValueSeparator, null),
+ new Tuple(JsonTokenType.Number, "0"),
+ new Tuple(JsonTokenType.ValueSeparator, null),
+ new Tuple(JsonTokenType.Number, "0.1"),
+ new Tuple(JsonTokenType.ValueSeparator, null),
+ new Tuple(JsonTokenType.Number, "-0.2"),
+ new Tuple(JsonTokenType.ValueSeparator, null),
+ new Tuple(JsonTokenType.Number, "-0.1e3"),
+ new Tuple(JsonTokenType.ValueSeparator, null),
+ new Tuple(JsonTokenType.Number, "1.3E-3"),
+ new Tuple(JsonTokenType.ValueSeparator, null),
+ new Tuple(JsonTokenType.String, "some \t\n text"),
+ new Tuple(JsonTokenType.ValueSeparator, null),
+ new Tuple(JsonTokenType.Literal, "literal"),
+ new Tuple(JsonTokenType.BeginArray, null),
+ new Tuple(JsonTokenType.EndArray, null),
+ new Tuple(JsonTokenType.BeginObject, null),
+ new Tuple(JsonTokenType.EndObject, null),
+ new Tuple(JsonTokenType.NameSeparator, null)
+ };
+
+ string value;
+ JsonTokenType tokenType;
+ for (var i = 0; i < expexted.Length; i++) {
+
+ Assert.True(scanner.ReadToken(out value, out tokenType));
+ Assert.Equal(expexted[i].Item1, tokenType);
+ Assert.Equal(expexted[i].Item2, value);
+ }
+
+ Assert.False(scanner.ReadToken(out value, out tokenType));
+ }
+ }
+
+ [Fact]
+ public void TestScannerBadTokens() {
+ var bad = new[] {
+ " 1",
+ " literal",
+ " \"",
+ "\"unclosed string",
+ "1.bad",
+ "001", // should be read as three numbers
+ "--10",
+ "+10",
+ "1.0.0",
+ "1e1.0",
+ "l1teral0",
+ ".123",
+ "-.123"
+ };
+
+ foreach (var json in bad) {
+ using (var scanner = JsonStringScanner.Create(json)) {
+ try {
+ string value;
+ JsonTokenType token;
+ scanner.ReadToken(out value, out token);
+ if (!Object.Equals(value, json)) {
+ Console.WriteLine("'{0}' is read as {1}", json, value is String ? String.Format("'{0}'", value) : value);
+ continue;
+ }
+ Assert.True(false, $"Token '{json}' shouldn't pass");
+ } catch (ParserException e) {
+ Console.WriteLine(e.Message);
+ }
+ }
+ }
+ }
+
+ [Fact]
+ public void JsonXmlReaderSimpleTest() {
+ var json = "\"some text\"";
+ //Console.WriteLine($"JSON: {json}");
+ //Console.WriteLine("XML");
+ /*using (var xmlReader = new JsonXmlReader(new JSONParser(json), new JsonXmlReaderOptions { NamespaceUri = "JsonXmlReaderSimpleTest", RootName = "string", NodesPrefix = "json" })) {
+ Assert.AreEqual(xmlReader.ReadState, System.Xml.ReadState.Initial);
+
+ AssertRead(xmlReader, XmlNodeType.XmlDeclaration);
+ AssertRead(xmlReader, XmlNodeType.Element);
+ AssertRead(xmlReader, XmlNodeType.Text);
+ AssertRead(xmlReader, XmlNodeType.EndElement);
+ Assert.IsFalse(xmlReader.Read());
+ }*/
+
+ DumpJsonParse("\"text value\"");
+ DumpJsonParse("null");
+ DumpJsonParse("true");
+ DumpJsonParse("{}");
+ DumpJsonParse("[]");
+ DumpJsonParse("{\"one\":1, \"two\":2}");
+ DumpJsonParse("[1,\"\",2,3]");
+ DumpJsonParse("[{\"info\": [7,8,9]}]");
+ DumpJsonFlatParse("[1,2,\"\",[3,4],{\"info\": [5,6]},{\"num\": [7,8,null]}, null,[null]]");
+ }
+
+ void AssertRead(XmlReader reader, XmlNodeType expected) {
+ Assert.True(reader.Read());
+ Console.WriteLine($"{new string(' ', reader.Depth * 2)}{reader}");
+ Assert.Equal(expected, reader.NodeType);
+ }
+
+ void DumpJsonParse(string json) {
+ Console.WriteLine($"JSON: {json}");
+ Console.WriteLine("XML");
+ using (var xmlWriter = XmlWriter.Create(Console.Out, new XmlWriterSettings {
+ Indent = true,
+ CloseOutput = false,
+ ConformanceLevel = ConformanceLevel.Document
+ }))
+ using (var xmlReader = new JsonXmlReader(JsonReader.ParseString(json), new JsonXmlReaderOptions { NamespaceUri = "JsonXmlReaderSimpleTest", NodesPrefix = "json" })) {
+ xmlWriter.WriteNode(xmlReader, false);
+ }
+ Console.WriteLine();
+ }
+
+ void DumpJsonFlatParse(string json) {
+ Console.WriteLine($"JSON: {json}");
+ Console.WriteLine("XML");
+ using (var xmlWriter = XmlWriter.Create(Console.Out, new XmlWriterSettings {
+ Indent = true,
+ CloseOutput = false,
+ ConformanceLevel = ConformanceLevel.Document
+ }))
+ using (var xmlReader = new JsonXmlReader(JsonReader.ParseString(json), new JsonXmlReaderOptions { NamespaceUri = "JsonXmlReaderSimpleTest", NodesPrefix = "", FlattenArrays = true })) {
+ xmlWriter.WriteNode(xmlReader, false);
+ }
+ Console.WriteLine();
+ }
+ }
+}
+
diff -r 05a87f575512 -r f1696cdc3d7a Implab.Test/MockPollComponent.cs
--- a/Implab.Test/MockPollComponent.cs Fri Apr 13 19:15:11 2018 +0300
+++ b/Implab.Test/MockPollComponent.cs Mon Apr 16 02:12:39 2018 +0300
@@ -21,11 +21,13 @@
}
protected async override Task StopInternalAsync(CancellationToken ct) {
+ await base.StopInternalAsync(ct);
if (StopWorker != null)
await StopWorker.Invoke(ct);
}
protected async override Task StartInternalAsync(CancellationToken ct) {
+ await base.StartInternalAsync(ct);
if (StartWorker != null)
await StartWorker.Invoke(ct);
}
diff -r 05a87f575512 -r f1696cdc3d7a Implab.Test/RunnableComponentTests.cs
--- a/Implab.Test/RunnableComponentTests.cs Fri Apr 13 19:15:11 2018 +0300
+++ b/Implab.Test/RunnableComponentTests.cs Mon Apr 16 02:12:39 2018 +0300
@@ -8,7 +8,7 @@
public class RunnableComponentTests {
[Fact]
- public async Task Test1() {
+ public async Task SimpleStartStop() {
using (var m = new MockPollComponent(true)) {
m.StartWorker = async (ct) => await Task.Yield();
@@ -16,12 +16,246 @@
Assert.Equal(ExecutionState.Ready, m.State);
Assert.NotNull(m.Completion);
-
- m.Start(CancellationToken.None);
+
+ m.Start();
await m.Completion;
Assert.Equal(ExecutionState.Running, m.State);
+ m.Stop();
+ await m.Completion;
+ Assert.Equal(ExecutionState.Stopped, m.State);
+ }
+ }
+
+ [Fact]
+ public async Task SyncStart() {
+ using (var m = new MockPollComponent(true)) {
+ m.Start();
+ Assert.Equal(ExecutionState.Running, m.State);
+ await m.Completion;
+ }
+ }
+
+ [Fact]
+ public async Task AsyncStarting() {
+ using (var m = new MockPollComponent(true)) {
+ var signal = Safe.CreateTask();
+
+ m.StartWorker = async (ct) => await signal;
+ m.Start();
+
+ Assert.Equal(ExecutionState.Starting, m.State);
+ Assert.False(m.Completion.IsCompleted);
+
+ signal.Start();
+
+ await m.Completion;
+
+ Assert.Equal(ExecutionState.Running, m.State);
+ }
+ }
+
+ [Fact]
+ public async Task FailWhileStarting() {
+ using (var m = new MockPollComponent(true)) {
+ const string failMessage = "Fail me";
+ var signal = new Task(() => {
+ throw new Exception(failMessage);
+ });
+
+ m.StartWorker = async (ct) => await signal;
+ m.Start();
+
+ Assert.Equal(ExecutionState.Starting, m.State);
+ Assert.False(m.Completion.IsCompleted);
+
+ signal.Start();
+ try {
+ await m.Completion;
+ Assert.True(false);
+ } catch (Exception e) {
+ Assert.Equal(failMessage, e.Message);
+ }
+
+ Assert.Equal(ExecutionState.Failed, m.State);
+ }
+ }
+
+ [Fact]
+ public async Task SyncStop() {
+ using (var m = new MockPollComponent(true)) {
+ m.Start();
+ Assert.Equal(ExecutionState.Running, m.State);
+ m.Stop();
+ Assert.Equal(ExecutionState.Stopped, m.State);
+ await m.Completion;
+ }
+ }
+
+ [Fact]
+ public async Task AsyncStopping() {
+ using (var m = new MockPollComponent(true)) {
+ var signal = Safe.CreateTask();
+
+ m.StopWorker = async (ct) => await signal;
+
+ // Start
+ m.Start();
+ Assert.Equal(ExecutionState.Running, m.State);
+
+ // Stop
+ m.Stop();
+ Assert.Equal(ExecutionState.Stopping, m.State);
+ Assert.False(m.Completion.IsCompleted);
+ signal.Start();
+
+ await m.Completion;
+
+ Assert.Equal(ExecutionState.Stopped, m.State);
+ }
+ }
+
+ [Fact]
+ public async Task FailWhileStopping() {
+ using (var m = new MockPollComponent(true)) {
+ const string failMessage = "Fail me";
+ var signal = new Task(() => {
+ throw new Exception(failMessage);
+ });
+
+ m.StopWorker = async (ct) => await signal;
+
+ // Start
+ m.Start();
+ Assert.Equal(ExecutionState.Running, m.State);
+
+ // Stop
+ m.Stop();
+ Assert.Equal(ExecutionState.Stopping, m.State);
+ Assert.False(m.Completion.IsCompleted);
+
+ signal.Start();
+ try {
+ await m.Completion;
+ Assert.True(false);
+ } catch (Exception e) {
+ Assert.Equal(failMessage, e.Message);
+ }
+
+ Assert.Equal(ExecutionState.Failed, m.State);
+ }
+ }
+
+ [Fact]
+ public async Task ThrowOnInvalidTrasition() {
+ using (var m = new MockPollComponent(false)) {
+ var started = Safe.CreateTask();
+ var stopped = Safe.CreateTask();
+
+ m.StartWorker = async (ct) => await started;
+ m.StopWorker = async (ct) => await stopped;
+
+ Assert.Throws(() => m.Start());
+
+ // Initialize
+ m.Initialize();
+ await m.Completion;
+
+ // Start
+ m.Start();
+ Assert.Equal(ExecutionState.Starting, m.State);
+
+ // Check invalid transitions
+ Assert.Throws(() => m.Start());
+
+ // Component can be stopped before started
+ // m.Stop(CancellationToken.None);
+
+ // Running
+ started.Start();
+ await m.Completion;
+ Assert.Equal(ExecutionState.Running, m.State);
+
+
+ Assert.Throws(() => m.Start());
+
+ // Stop
+ m.Stop();
+
+ // Check invalid transitions
+ Assert.Throws(() => m.Start());
+ Assert.Throws(() => m.Stop());
+
+ // Stopped
+ stopped.Start();
+ await m.Completion;
+ Assert.Equal(ExecutionState.Stopped, m.State);
+
+ // Check invalid transitions
+ Assert.Throws(() => m.Start());
+ Assert.Throws(() => m.Stop());
+ }
+ }
+
+ [Fact]
+ public async Task CancelStart() {
+ using (var m = new MockPollComponent(true)) {
+ m.StartWorker = (ct) => Safe.CreateTask(ct);
+
+ m.Start();
+ var start = m.Completion;
+
+ Assert.Equal(ExecutionState.Starting, m.State);
+ m.Stop();
+ await m.Completion;
+ Assert.Equal(ExecutionState.Stopped, m.State);
+ Assert.True(start.IsCompleted);
+ Assert.True(start.IsCanceled);
+ }
+ }
+
+ [Fact]
+ public async Task AwaitWorker() {
+ using (var m = new MockPollComponent(true)) {
+ var worker = Safe.CreateTask();
+
+ m.PollWorker = (ct) => worker;
+
+ m.Start(CancellationToken.None);
+ await m.Completion;
+
+ Assert.Equal(ExecutionState.Running, m.State);
+
m.Stop(CancellationToken.None);
+ Assert.Equal(ExecutionState.Stopping, m.State);
+ worker.Start();
+ await m.Completion;
+ Assert.Equal(ExecutionState.Stopped, m.State);
+ }
+ }
+
+ [Fact]
+ public async Task CancelWorker() {
+ using (var m = new MockPollComponent(true)) {
+ var worker = Safe.CreateTask();
+
+ var started = Safe.CreateTask();
+
+ m.PollWorker = async (ct) => {
+ started.Start();
+ await worker;
+ ct.ThrowIfCancellationRequested();
+ };
+
+ m.Start(CancellationToken.None);
+ await m.Completion;
+ await started; // await for the poll worker to start
+
+ Assert.Equal(ExecutionState.Running, m.State);
+
+ m.Stop(CancellationToken.None);
+ Assert.Equal(ExecutionState.Stopping, m.State);
+ worker.Start();
await m.Completion;
Assert.Equal(ExecutionState.Stopped, m.State);
}
diff -r 05a87f575512 -r f1696cdc3d7a Implab/Components/IInitializable.cs
--- a/Implab/Components/IInitializable.cs Fri Apr 13 19:15:11 2018 +0300
+++ b/Implab/Components/IInitializable.cs Mon Apr 16 02:12:39 2018 +0300
@@ -1,4 +1,5 @@
using System;
+using System.Threading;
namespace Implab.Components {
///
@@ -23,6 +24,7 @@
///
///
void Initialize();
+ void Initialize(CancellationToken ct);
}
}
diff -r 05a87f575512 -r f1696cdc3d7a Implab/Components/IRunnable.cs
--- a/Implab/Components/IRunnable.cs Fri Apr 13 19:15:11 2018 +0300
+++ b/Implab/Components/IRunnable.cs Mon Apr 16 02:12:39 2018 +0300
@@ -19,6 +19,7 @@
/// This operation is cancellable and it's expected to move to
/// the failed state or just ignore the cancellation request,
///
+ void Start();
void Start(CancellationToken ct);
///
@@ -31,8 +32,9 @@
/// will be requested to cancel. The stop operatin will be
/// performed only if the component in the running state.
///
+ void Stop();
void Stop(CancellationToken ct);
-
+
///
/// Current state of the componenet, dynamically reflects the current state.
///
diff -r 05a87f575512 -r f1696cdc3d7a Implab/Components/PollingComponent.cs
--- a/Implab/Components/PollingComponent.cs Fri Apr 13 19:15:11 2018 +0300
+++ b/Implab/Components/PollingComponent.cs Mon Apr 16 02:12:39 2018 +0300
@@ -49,7 +49,8 @@
m_cancellation.Cancel();
try {
// await for pending poll
- await m_poll;
+ if (m_poll != null)
+ await m_poll;
} catch (OperationCanceledException) {
// OK
}
diff -r 05a87f575512 -r f1696cdc3d7a Implab/Components/RunnableComponent.cs
--- a/Implab/Components/RunnableComponent.cs Fri Apr 13 19:15:11 2018 +0300
+++ b/Implab/Components/RunnableComponent.cs Mon Apr 16 02:12:39 2018 +0300
@@ -171,9 +171,13 @@
}
public void Initialize() {
+ Initialize(CancellationToken.None);
+ }
+
+ public void Initialize(CancellationToken ct) {
var cookie = new object();
if (MoveInitialize(cookie))
- Safe.NoWait(ScheduleTask(InitializeInternalAsync, CancellationToken.None, cookie));
+ Safe.NoWait(ScheduleTask(InitializeInternalAsync, ct, cookie));
else
throw new InvalidOperationException();
}
@@ -191,6 +195,10 @@
return Task.CompletedTask;
}
+ public void Start() {
+ Start(CancellationToken.None);
+ }
+
public void Start(CancellationToken ct) {
var cookie = new object();
if (MoveStart(cookie))
@@ -220,6 +228,10 @@
}
+ public void Stop() {
+ Stop(CancellationToken.None);
+ }
+
public void Stop(CancellationToken ct) {
var cookie = new object();
if (MoveStop(cookie))
@@ -230,7 +242,12 @@
async Task StopAsync(CancellationToken ct) {
m_current.Cancel();
- await Completion;
+
+ try {
+ await Completion;
+ } catch(OperationCanceledException) {
+ // OK
+ }
ct.ThrowIfCancellationRequested();
@@ -302,12 +319,13 @@
}
}
- void MoveFailed(Exception err, object cookie) {
+ bool MoveFailed(Exception err, object cookie) {
lock (m_lock) {
if (m_cookie != cookie)
- return;
+ return false;
LastError = err;
State = ExecutionState.Failed;
+ return true;
}
}
diff -r 05a87f575512 -r f1696cdc3d7a Implab/Implab.csproj
--- a/Implab/Implab.csproj Fri Apr 13 19:15:11 2018 +0300
+++ b/Implab/Implab.csproj Mon Apr 16 02:12:39 2018 +0300
@@ -8,8 +8,8 @@
and SharedLock, Trace helpers on top of System.Diagnostics, ObjectPool etc.
2012-2018 Sergey Smirnov
- 3.0.6
- https://opensource.org/licenses/BSD-2-Clause
+ 3.0.8
+ https://hg.implab.org/pub/ImplabNet/file/tip/Implab/license.txt
https://implab.org
https://hg.implab.org/pub/ImplabNet/
mercurial