# HG changeset patch # User cin # Date 1479050897 -10800 # Node ID 7d07503621fef9c681a883b986f5d8c717135874 # Parent 558f34b2fb50f2b375ca1a419c6d352e24139c84 RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool) IRunnable is now disposable Code cleanups, suppressed some CodeAnalysis warnings diff -r 558f34b2fb50 -r 7d07503621fe Implab.Test/Mock/MockRunnableComponent.cs --- a/Implab.Test/Mock/MockRunnableComponent.cs Wed Nov 09 12:03:22 2016 +0300 +++ b/Implab.Test/Mock/MockRunnableComponent.cs Sun Nov 13 18:28:17 2016 +0300 @@ -24,7 +24,7 @@ set; } - public Action MockDispose { + public Action MockDispose { get; set; } @@ -42,10 +42,10 @@ MockInit(); } - protected override void Dispose(bool disposing, Exception lastError) { + protected override void Dispose(bool disposing) { if (MockDispose != null) - MockDispose(disposing, lastError); - base.Dispose(disposing, lastError); + MockDispose(disposing); + base.Dispose(disposing); } } } diff -r 558f34b2fb50 -r 7d07503621fe Implab.Test/RunnableComponentTests.cs --- a/Implab.Test/RunnableComponentTests.cs Wed Nov 09 12:03:22 2016 +0300 +++ b/Implab.Test/RunnableComponentTests.cs Sun Nov 13 18:28:17 2016 +0300 @@ -95,7 +95,7 @@ var comp = new MockRunnableComponent(true); bool disposed = false; - comp.MockDispose = (disposing, error) => { + comp.MockDispose = (disposing) => { disposed = true; }; @@ -115,7 +115,7 @@ var comp = new MockRunnableComponent(true, true); bool disposed = false; - comp.MockDispose = (disposing, error) => { + comp.MockDispose = (disposing) => { disposed = true; }; @@ -131,10 +131,8 @@ var comp = new MockRunnableComponent(true, true); bool disposed = false; - Exception lastError = null; - comp.MockDispose = (disposing, error) => { + comp.MockDispose = (disposing) => { disposed = true; - lastError = error; }; comp.Start().Join(1000); diff -r 558f34b2fb50 -r 7d07503621fe Implab/Components/Disposable.cs --- a/Implab/Components/Disposable.cs Wed Nov 09 12:03:22 2016 +0300 +++ b/Implab/Components/Disposable.cs Sun Nov 13 18:28:17 2016 +0300 @@ -1,5 +1,6 @@ using Implab.Diagnostics; using System; +using System.Diagnostics.CodeAnalysis; using System.Threading; namespace Implab.Components { @@ -81,6 +82,7 @@ } } + [SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "Dipose(bool) and GC.SuppessFinalize are called")] public void Dispose() { if (Interlocked.Increment(ref m_disposed) == 1) { Dispose(true); diff -r 558f34b2fb50 -r 7d07503621fe Implab/Components/IRunnable.cs --- a/Implab/Components/IRunnable.cs Wed Nov 09 12:03:22 2016 +0300 +++ b/Implab/Components/IRunnable.cs Sun Nov 13 18:28:17 2016 +0300 @@ -1,14 +1,22 @@ using System; namespace Implab.Components { - public interface IRunnable { + /// + /// Interface for the component which performs a long running task. + /// + /// + /// The component also should implement interface to be able to release used resources. + /// All methods of this interface must be a thread safe. If the operation is not applicable in the current state the + /// method should throw an exception and keep the current state unchanged. + /// + public interface IRunnable : IDisposable { /// - /// Starts this instance. + /// Starts this instance /// IPromise Start(); /// - /// Stops this instance. After the instance is stopped it can't be started again, stopping should be treated as gracefull and async dispose. + /// Stops this instance, after the instance is stopped it can move to Failed, Ready or Disposed state, in case with the last it can't be reused. /// IPromise Stop(); diff -r 558f34b2fb50 -r 7d07503621fe Implab/Components/PollingComponent.cs --- a/Implab/Components/PollingComponent.cs Wed Nov 09 12:03:22 2016 +0300 +++ b/Implab/Components/PollingComponent.cs Sun Nov 13 18:28:17 2016 +0300 @@ -144,11 +144,11 @@ return base.OnStop(); } - protected override void Dispose(bool disposing, Exception lastError) { + protected override void Dispose(bool disposing) { if (disposing) - Safe.Dispose(m_timer); + m_timer.Dispose(); - base.Dispose(disposing, lastError); + base.Dispose(disposing); } } } diff -r 558f34b2fb50 -r 7d07503621fe Implab/Components/RunnableComponent.cs --- a/Implab/Components/RunnableComponent.cs Wed Nov 09 12:03:22 2016 +0300 +++ b/Implab/Components/RunnableComponent.cs Sun Nov 13 18:28:17 2016 +0300 @@ -1,5 +1,6 @@ using System; - +using System.Diagnostics.CodeAnalysis; + namespace Implab.Components { public abstract class RunnableComponent : IDisposable, IRunnable, IInitializable { enum Commands { @@ -333,30 +334,22 @@ /// especially if method is failed. Using this method insted of may /// lead to the data loss by the component. /// + [SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "Dipose(bool) and GC.SuppessFinalize are called")] public void Dispose() { IPromise pending; lock (m_stateMachine) { if (m_stateMachine.State == ExecutionState.Disposed) return; - pending = Move(Commands.Dispose, null, null); + Move(Commands.Dispose, null, null); } GC.SuppressFinalize(this); - if (pending != null) { - pending.Cancel(); - pending.Timeout(DisposeTimeout).On( - () => Dispose(true, null), - err => Dispose(true, err), - reason => Dispose(true, new OperationCanceledException("The operation is cancelled", reason)) - ); - } else { - Dispose(true, null); - } + Dispose(true); } ~RunnableComponent() { - Dispose(false, null); + Dispose(false); } #endregion @@ -365,8 +358,8 @@ /// Releases all resources used by the component, called automatically, override this method to implement your cleanup. /// /// true if this method is called during normal dispose process. - /// The last error which occured during the component stop. - protected virtual void Dispose(bool disposing, Exception lastError) { + /// The operation which is currenty pending + protected virtual void Dispose(bool disposing) { } diff -r 558f34b2fb50 -r 7d07503621fe Implab/Formats/JSON/JSONParser.cs --- a/Implab/Formats/JSON/JSONParser.cs Wed Nov 09 12:03:22 2016 +0300 +++ b/Implab/Formats/JSON/JSONParser.cs Sun Nov 13 18:28:17 2016 +0300 @@ -274,7 +274,7 @@ protected override void Dispose(bool disposing) { if (disposing) - Safe.Dispose(m_scanner); + m_scanner.Dispose(); } /// diff -r 558f34b2fb50 -r 7d07503621fe Implab/Formats/JSON/JSONScanner.cs --- a/Implab/Formats/JSON/JSONScanner.cs Wed Nov 09 12:03:22 2016 +0300 +++ b/Implab/Formats/JSON/JSONScanner.cs Sun Nov 13 18:28:17 2016 +0300 @@ -102,7 +102,7 @@ protected override void Dispose(bool disposing) { if (disposing) - Safe.Dispose(m_scanner); + m_scanner.Dispose(); base.Dispose(disposing); } } diff -r 558f34b2fb50 -r 7d07503621fe Implab/PromiseExtensions.cs --- a/Implab/PromiseExtensions.cs Wed Nov 09 12:03:22 2016 +0300 +++ b/Implab/PromiseExtensions.cs Sun Nov 13 18:28:17 2016 +0300 @@ -120,8 +120,12 @@ } public static IPromise PromiseAll(this IEnumerable> that) { + return PromiseAll(that, null); + } + + public static IPromise PromiseAll(this IEnumerable> that, Action cleanup) { Safe.ArgumentNotNull(that, "that"); - return PromiseAll(that.ToList()); + return PromiseAll(that.ToList(), cleanup); } public static IPromise PromiseAll(this ICollection that) { @@ -164,17 +168,35 @@ return medium; } - public static IPromise PromiseAll(this ICollection> that) { + public static IPromise PromiseAll(this ICollection> that) { + return PromiseAll(that, null); + } + + /// + /// Creates a new promise which will be satisfied when all promises are satisfied. + /// + /// + /// + /// A callback used to cleanup already resolved promises in case of an error + /// + public static IPromise PromiseAll(this ICollection> that, Action cleanup) { Safe.ArgumentNotNull(that, "that"); + + int count = that.Count; - int count = that.Count; + if (count == 0) + return Promise.FromResult(new T[0]); + int errors = 0; var medium = new Promise(); var results = new T[that.Count]; medium.On(() => { - foreach (var p2 in that) - p2.Cancel(); + foreach (var p2 in that) { + p2.Cancel(); + if (cleanup != null) + p2.On(cleanup); + } }, PromiseEventType.ErrorOrCancel); int i = 0; @@ -414,6 +436,12 @@ return new PromiseAwaiter(that); } + public static PromiseAwaiter GetAwaiter(this IPromise that) { + Safe.ArgumentNotNull(that, "that"); + + return new PromiseAwaiter(that); + } + #endif } }