diff --git a/Implab/Components/Disposable.cs b/Implab/Components/Disposable.cs --- a/Implab/Components/Disposable.cs +++ b/Implab/Components/Disposable.cs @@ -9,15 +9,10 @@ namespace Implab.Components { /// public class Disposable : IDisposable { - int m_disposed; - public event EventHandler Disposed; public bool IsDisposed { - get { - Thread.MemoryBarrier(); - return m_disposed != 0; - } + get; private set; } /// @@ -25,43 +20,8 @@ namespace Implab.Components { /// /// The object is disposed /// - /// Успешная проверка того, что объект не освобожден еще не гарантирует, что он не - /// будет освобожден сразу после нее, поэтому методы использующие проверку должны - /// учитывать, что объект может быть освобожден из параллельного потока. - /// Данны метод служит для упрощения отладки ошибок при использовании объекта после его - /// освобождения. - /// - /// - /// // пример синхронизированного освобождения ресурсов - /// class FileStore : Disposable { - /// readonly TextWriter m_file; - /// readonly obejct m_sync = new object(); - /// - /// public FileStore(string file) { - /// m_file = new TextWriter(File.OpenWrite(file)); - /// } - /// - /// public void Write(string text) { - /// lock(m_sync) { - /// AssertNotDisposed(); - /// m_file.Write(text); - /// } - /// } - /// - /// protected override void Dispose(bool disposing) { - /// if (disposing) - /// lock(m_sync) { - /// m_file.Dipose(); - /// base.Dispose(true); - /// } - /// else - /// base.Dispose(false); - /// } - /// } - /// protected void AssertNotDisposed() { - Thread.MemoryBarrier(); - if (m_disposed != 0) + if (IsDisposed) throw new ObjectDisposedException(ToString()); } /// @@ -77,12 +37,12 @@ namespace Implab.Components { protected virtual void Dispose(bool disposing) { if (disposing) Disposed.DispatchEvent(this, EventArgs.Empty); - } [SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "Dipose(bool) and GC.SuppessFinalize are called")] public void Dispose() { - if (Interlocked.Increment(ref m_disposed) == 1) { + if(!IsDisposed) { + IsDisposed = true; Dispose(true); GC.SuppressFinalize(this); } diff --git a/Implab/Components/ExecutionState.cs b/Implab/Components/ExecutionState.cs --- a/Implab/Components/ExecutionState.cs +++ b/Implab/Components/ExecutionState.cs @@ -13,12 +13,6 @@ Running, - Suspending, - - Suspended, - - Resuming, - Stopping, Failed, diff --git a/Implab/Components/IInitializable.cs b/Implab/Components/IInitializable.cs --- a/Implab/Components/IInitializable.cs +++ b/Implab/Components/IInitializable.cs @@ -12,7 +12,7 @@ namespace Implab.Components { /// /// /// Normally virtual methods shouldn't be called from the constructor, due to the incomplete object state, but - /// they can be called from this method. This method is aьуерщlso usefull when we constructing a complex grpah + /// they can be called from this method. This method is also usefull when we constructing a complex grpah /// of components where cyclic references may take place. /// void Initialize(); diff --git a/Implab/Components/IRunnable.cs b/Implab/Components/IRunnable.cs --- a/Implab/Components/IRunnable.cs +++ b/Implab/Components/IRunnable.cs @@ -1,24 +1,23 @@ using System; +using System.Threading; +using System.Threading.Tasks; namespace Implab.Components { - /// - /// Interface for the component which performs a long running task. + /// + /// 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 /// - IPromise Start(); + void Start(CancellationToken ct); /// - /// 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. + /// Stops this instance and releases all resources, after the instance is stopped it is moved to Disposed state and can't be reused. /// - IPromise Stop(); + void Stop(CancellationToken ct); + + Task Completion { get; } ExecutionState State { get; } diff --git a/Implab/Components/IServiceLocator.cs b/Implab/Components/IServiceLocator.cs new file mode 100644 --- /dev/null +++ b/Implab/Components/IServiceLocator.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Implab.Components { + public interface IServiceLocator: IServiceProvider { + T GetService(); + bool TryGetService(out T service); + bool TryGetService (Type serviceType, out object service); + } +} diff --git a/Implab/Components/RunnableComponent.cs b/Implab/Components/RunnableComponent.cs new file mode 100644 --- /dev/null +++ b/Implab/Components/RunnableComponent.cs @@ -0,0 +1,57 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Implab.Components +{ + public class RunnableComponent : IRunnable { + + readonly object m_lock = new object(); + + CancellationTokenSource m_cts; + + public Task Completion { + get; + private set; + } + + public ExecutionState State => throw new NotImplementedException(); + + public Exception LastError => throw new NotImplementedException(); + + public event EventHandler StateChanged; + + public void Dispose() { + lock(m_lock) { + Dispose(true); + GC.SuppressFinalize(this); + } + } + + protected virtual void Dispose(bool disposing) { + if (disposing) { + Safe.Dispose(m_cts); + } + } + + public void Start(CancellationToken ct) { + lock(m_lock) { + switch (State) + { + + default: + throw new InvalidOperationException(); + } + } + } + + public void Stop(CancellationToken ct) { + throw new NotImplementedException(); + } + + protected virtual Task StartImpl(CancellationToken ct) { + + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/Implab/IServiceLocator.cs b/Implab/IServiceLocator.cs deleted file mode 100644 --- a/Implab/IServiceLocator.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab { - public interface IServiceLocator: IServiceProvider { - T GetService(); - bool TryGetService(out T service); - bool TryGetService (Type serviceType, out object service); - } -} diff --git a/Implab/Messaging/IConsumer.cs b/Implab/Messaging/IConsumer.cs new file mode 100644 --- /dev/null +++ b/Implab/Messaging/IConsumer.cs @@ -0,0 +1,10 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace Implab.Messaging { + public interface IConsumer { + Task Receive(CancellationToken ct); + + bool TryReceive(out T message); + } +} \ No newline at end of file diff --git a/Implab/Messaging/IProducer.cs b/Implab/Messaging/IProducer.cs new file mode 100644 --- /dev/null +++ b/Implab/Messaging/IProducer.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace Implab.Messaging { + public interface IProducer { + Task PostMessageAsync(T message, CancellationToken ct); + + Task PostMessagesAsync(IEnumerable messages, CancellationToken ct); + } +} \ No newline at end of file