Auto status change to "Under Review"
@@ -0,0 +1,13 | |||||
|
1 | using System; | |||
|
2 | using System.Collections.Generic; | |||
|
3 | using System.Linq; | |||
|
4 | using System.Text; | |||
|
5 | using System.Threading.Tasks; | |||
|
6 | ||||
|
7 | namespace Implab.Components { | |||
|
8 | public interface IServiceLocator: IServiceProvider { | |||
|
9 | T GetService<T>(); | |||
|
10 | bool TryGetService<T>(out T service); | |||
|
11 | bool TryGetService (Type serviceType, out object service); | |||
|
12 | } | |||
|
13 | } |
@@ -0,0 +1,57 | |||||
|
1 | using System; | |||
|
2 | using System.Threading; | |||
|
3 | using System.Threading.Tasks; | |||
|
4 | ||||
|
5 | namespace Implab.Components | |||
|
6 | { | |||
|
7 | public class RunnableComponent : IRunnable { | |||
|
8 | ||||
|
9 | readonly object m_lock = new object(); | |||
|
10 | ||||
|
11 | CancellationTokenSource m_cts; | |||
|
12 | ||||
|
13 | public Task<ExecutionState> Completion { | |||
|
14 | get; | |||
|
15 | private set; | |||
|
16 | } | |||
|
17 | ||||
|
18 | public ExecutionState State => throw new NotImplementedException(); | |||
|
19 | ||||
|
20 | public Exception LastError => throw new NotImplementedException(); | |||
|
21 | ||||
|
22 | public event EventHandler<StateChangeEventArgs> StateChanged; | |||
|
23 | ||||
|
24 | public void Dispose() { | |||
|
25 | lock(m_lock) { | |||
|
26 | Dispose(true); | |||
|
27 | GC.SuppressFinalize(this); | |||
|
28 | } | |||
|
29 | } | |||
|
30 | ||||
|
31 | protected virtual void Dispose(bool disposing) { | |||
|
32 | if (disposing) { | |||
|
33 | Safe.Dispose(m_cts); | |||
|
34 | } | |||
|
35 | } | |||
|
36 | ||||
|
37 | public void Start(CancellationToken ct) { | |||
|
38 | lock(m_lock) { | |||
|
39 | switch (State) | |||
|
40 | { | |||
|
41 | ||||
|
42 | default: | |||
|
43 | throw new InvalidOperationException(); | |||
|
44 | } | |||
|
45 | } | |||
|
46 | } | |||
|
47 | ||||
|
48 | public void Stop(CancellationToken ct) { | |||
|
49 | throw new NotImplementedException(); | |||
|
50 | } | |||
|
51 | ||||
|
52 | protected virtual Task StartImpl(CancellationToken ct) { | |||
|
53 | ||||
|
54 | return Task.CompletedTask; | |||
|
55 | } | |||
|
56 | } | |||
|
57 | } No newline at end of file |
@@ -0,0 +1,10 | |||||
|
1 | using System.Threading; | |||
|
2 | using System.Threading.Tasks; | |||
|
3 | ||||
|
4 | namespace Implab.Messaging { | |||
|
5 | public interface IConsumer<T> { | |||
|
6 | Task<T> Receive(CancellationToken ct); | |||
|
7 | ||||
|
8 | bool TryReceive(out T message); | |||
|
9 | } | |||
|
10 | } No newline at end of file |
@@ -0,0 +1,11 | |||||
|
1 | using System.Collections.Generic; | |||
|
2 | using System.Threading; | |||
|
3 | using System.Threading.Tasks; | |||
|
4 | ||||
|
5 | namespace Implab.Messaging { | |||
|
6 | public interface IProducer<T> { | |||
|
7 | Task PostMessageAsync(T message, CancellationToken ct); | |||
|
8 | ||||
|
9 | Task PostMessagesAsync(IEnumerable<T> messages, CancellationToken ct); | |||
|
10 | } | |||
|
11 | } No newline at end of file |
@@ -1,103 +1,63 | |||||
1 | using Implab.Diagnostics; |
|
1 | using Implab.Diagnostics; | |
2 | using System; |
|
2 | using System; | |
3 | using System.Diagnostics.CodeAnalysis; |
|
3 | using System.Diagnostics.CodeAnalysis; | |
4 | using System.Threading; |
|
4 | using System.Threading; | |
5 |
|
5 | |||
6 | namespace Implab.Components { |
|
6 | namespace Implab.Components { | |
7 | /// <summary> |
|
7 | /// <summary> | |
8 | /// Base class the objects which support disposing. |
|
8 | /// Base class the objects which support disposing. | |
9 | /// </summary> |
|
9 | /// </summary> | |
10 | public class Disposable : IDisposable { |
|
10 | public class Disposable : IDisposable { | |
11 |
|
11 | |||
12 | int m_disposed; |
|
|||
13 |
|
||||
14 | public event EventHandler Disposed; |
|
12 | public event EventHandler Disposed; | |
15 |
|
13 | |||
16 | public bool IsDisposed { |
|
14 | public bool IsDisposed { | |
17 |
get |
|
15 | get; private set; | |
18 | Thread.MemoryBarrier(); |
|
|||
19 | return m_disposed != 0; |
|
|||
20 | } |
|
|||
21 | } |
|
16 | } | |
22 |
|
17 | |||
23 | /// <summary> |
|
18 | /// <summary> | |
24 | /// Asserts the object is not disposed. |
|
19 | /// Asserts the object is not disposed. | |
25 | /// </summary> |
|
20 | /// </summary> | |
26 | /// <exception cref="ObjectDisposedException">The object is disposed</exception> |
|
21 | /// <exception cref="ObjectDisposedException">The object is disposed</exception> | |
27 | /// <remarks> |
|
22 | /// <remarks> | |
28 | /// Успешная проверка того, что объект не освобожден еще не гарантирует, что он не |
|
|||
29 | /// будет освобожден сразу после нее, поэтому методы использующие проверку должны |
|
|||
30 | /// учитывать, что объект может быть освобожден из параллельного потока. |
|
|||
31 | /// Данны метод служит для упрощения отладки ошибок при использовании объекта после его |
|
|||
32 | /// освобождения. |
|
|||
33 | /// </remarks> |
|
|||
34 | /// <example> |
|
|||
35 | /// // пример синхронизированного освобождения ресурсов |
|
|||
36 | /// class FileStore : Disposable { |
|
|||
37 | /// readonly TextWriter m_file; |
|
|||
38 | /// readonly obejct m_sync = new object(); |
|
|||
39 | /// |
|
|||
40 | /// public FileStore(string file) { |
|
|||
41 | /// m_file = new TextWriter(File.OpenWrite(file)); |
|
|||
42 | /// } |
|
|||
43 | /// |
|
|||
44 | /// public void Write(string text) { |
|
|||
45 | /// lock(m_sync) { |
|
|||
46 | /// AssertNotDisposed(); |
|
|||
47 | /// m_file.Write(text); |
|
|||
48 | /// } |
|
|||
49 | /// } |
|
|||
50 | /// |
|
|||
51 | /// protected override void Dispose(bool disposing) { |
|
|||
52 | /// if (disposing) |
|
|||
53 | /// lock(m_sync) { |
|
|||
54 | /// m_file.Dipose(); |
|
|||
55 | /// base.Dispose(true); |
|
|||
56 | /// } |
|
|||
57 | /// else |
|
|||
58 | /// base.Dispose(false); |
|
|||
59 | /// } |
|
|||
60 | /// } |
|
|||
61 | /// <example> |
|
|||
62 | protected void AssertNotDisposed() { |
|
23 | protected void AssertNotDisposed() { | |
63 | Thread.MemoryBarrier(); |
|
24 | if (IsDisposed) | |
64 | if (m_disposed != 0) |
|
|||
65 | throw new ObjectDisposedException(ToString()); |
|
25 | throw new ObjectDisposedException(ToString()); | |
66 | } |
|
26 | } | |
67 | /// <summary> |
|
27 | /// <summary> | |
68 | /// Вызывает событие <see cref="Disposed"/> |
|
28 | /// Вызывает событие <see cref="Disposed"/> | |
69 | /// </summary> |
|
29 | /// </summary> | |
70 | /// <param name="disposing">Признак того, что нужно освободить ресурсы, иначе данный метод |
|
30 | /// <param name="disposing">Признак того, что нужно освободить ресурсы, иначе данный метод | |
71 | /// вызван сборщиком мусора и нужно освобождать ТОЛЬКО неуправляемые ресурсы ТОЛЬКО этого |
|
31 | /// вызван сборщиком мусора и нужно освобождать ТОЛЬКО неуправляемые ресурсы ТОЛЬКО этого | |
72 | /// объекта.</param> |
|
32 | /// объекта.</param> | |
73 | /// <remarks> |
|
33 | /// <remarks> | |
74 | /// Данный метод вызывается гарантированно один раз даже при одновременном вызове <see cref="Dispose()"/> |
|
34 | /// Данный метод вызывается гарантированно один раз даже при одновременном вызове <see cref="Dispose()"/> | |
75 | /// из нескольких потоков. |
|
35 | /// из нескольких потоков. | |
76 | /// </remarks> |
|
36 | /// </remarks> | |
77 | protected virtual void Dispose(bool disposing) { |
|
37 | protected virtual void Dispose(bool disposing) { | |
78 | if (disposing) |
|
38 | if (disposing) | |
79 | Disposed.DispatchEvent(this, EventArgs.Empty); |
|
39 | Disposed.DispatchEvent(this, EventArgs.Empty); | |
80 |
|
||||
81 | } |
|
40 | } | |
82 |
|
41 | |||
83 | [SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "Dipose(bool) and GC.SuppessFinalize are called")] |
|
42 | [SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "Dipose(bool) and GC.SuppessFinalize are called")] | |
84 | public void Dispose() { |
|
43 | public void Dispose() { | |
85 | if (Interlocked.Increment(ref m_disposed) == 1) { |
|
44 | if(!IsDisposed) { | |
|
45 | IsDisposed = true; | |||
86 | Dispose(true); |
|
46 | Dispose(true); | |
87 | GC.SuppressFinalize(this); |
|
47 | GC.SuppressFinalize(this); | |
88 | } |
|
48 | } | |
89 | } |
|
49 | } | |
90 |
|
50 | |||
91 | /// <summary> |
|
51 | /// <summary> | |
92 | /// Записывает сообщение об утечке объекта. |
|
52 | /// Записывает сообщение об утечке объекта. | |
93 | /// </summary> |
|
53 | /// </summary> | |
94 | protected virtual void ReportObjectLeaks() { |
|
54 | protected virtual void ReportObjectLeaks() { | |
95 | TraceLog.TraceWarning("The object is marked as disposable but isn't disposed properly: {0}", this); |
|
55 | TraceLog.TraceWarning("The object is marked as disposable but isn't disposed properly: {0}", this); | |
96 | } |
|
56 | } | |
97 |
|
57 | |||
98 | ~Disposable() { |
|
58 | ~Disposable() { | |
99 | Dispose(false); |
|
59 | Dispose(false); | |
100 | ReportObjectLeaks(); |
|
60 | ReportObjectLeaks(); | |
101 | } |
|
61 | } | |
102 | } |
|
62 | } | |
103 | } No newline at end of file |
|
63 | } |
@@ -1,30 +1,24 | |||||
1 | namespace Implab.Components { |
|
1 | namespace Implab.Components { | |
2 |
|
2 | |||
3 | public enum ExecutionState { |
|
3 | public enum ExecutionState { | |
4 | Undefined = 0, |
|
4 | Undefined = 0, | |
5 |
|
5 | |||
6 | Created, |
|
6 | Created, | |
7 |
|
7 | |||
8 | Initializing, |
|
8 | Initializing, | |
9 |
|
9 | |||
10 | Ready, |
|
10 | Ready, | |
11 |
|
11 | |||
12 | Starting, |
|
12 | Starting, | |
13 |
|
13 | |||
14 | Running, |
|
14 | Running, | |
15 |
|
15 | |||
16 | Suspending, |
|
|||
17 |
|
||||
18 | Suspended, |
|
|||
19 |
|
||||
20 | Resuming, |
|
|||
21 |
|
||||
22 | Stopping, |
|
16 | Stopping, | |
23 |
|
17 | |||
24 | Failed, |
|
18 | Failed, | |
25 |
|
19 | |||
26 | Disposed, |
|
20 | Disposed, | |
27 |
|
21 | |||
28 | Last = Disposed |
|
22 | Last = Disposed | |
29 | } |
|
23 | } | |
30 | } No newline at end of file |
|
24 | } |
@@ -1,21 +1,21 | |||||
1 | using System; |
|
1 | using System; | |
2 |
|
2 | |||
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="Initialize()"/> 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="Initialize()"/> |
|
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> | |
11 | /// Completes initialization. |
|
11 | /// Completes initialization. | |
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 a |
|
15 | /// they can be called from this method. This method is also 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 Initialize(); |
|
18 | void Initialize(); | |
19 | } |
|
19 | } | |
20 | } |
|
20 | } | |
21 |
|
21 |
@@ -1,30 +1,29 | |||||
1 | using System; |
|
1 | using System; | |
|
2 | using System.Threading; | |||
|
3 | using System.Threading.Tasks; | |||
2 |
|
4 | |||
3 | namespace Implab.Components { |
|
5 | namespace Implab.Components { | |
4 | /// <summary> |
|
6 | /// <summary> | |
5 | /// Interface for the component which performs a long running task. |
|
7 | /// Interface for the component which performs a long running task. | |
6 | /// </summary> |
|
8 | /// </summary> | |
7 | /// <remarks> |
|
|||
8 | /// <para>The component also should implement <see cref="IDisposable"/> interface to be able to release used resources.</para> |
|
|||
9 | /// <para>All methods of this interface must be a thread safe. If the operation is not applicable in the current state the |
|
|||
10 | /// method should throw an exception and keep the current state unchanged.</para> |
|
|||
11 | /// </remarks> |
|
|||
12 | public interface IRunnable : IDisposable { |
|
9 | public interface IRunnable : IDisposable { | |
13 | /// <summary> |
|
10 | /// <summary> | |
14 | /// Starts this instance |
|
11 | /// Starts this instance | |
15 | /// </summary> |
|
12 | /// </summary> | |
16 | IPromise Start(); |
|
13 | void Start(CancellationToken ct); | |
17 |
|
14 | |||
18 | /// <summary> |
|
15 | /// <summary> | |
19 |
/// Stops this instance, after the instance is stopped it |
|
16 | /// Stops this instance and releases all resources, after the instance is stopped it is moved to Disposed state and can't be reused. | |
20 | /// </summary> |
|
17 | /// </summary> | |
21 | IPromise Stop(); |
|
18 | void Stop(CancellationToken ct); | |
|
19 | ||||
|
20 | Task<ExecutionState> Completion { get; } | |||
22 |
|
21 | |||
23 | ExecutionState State { get; } |
|
22 | ExecutionState State { get; } | |
24 |
|
23 | |||
25 | event EventHandler<StateChangeEventArgs> StateChanged; |
|
24 | event EventHandler<StateChangeEventArgs> StateChanged; | |
26 |
|
25 | |||
27 | Exception LastError { get; } |
|
26 | Exception LastError { get; } | |
28 | } |
|
27 | } | |
29 | } |
|
28 | } | |
30 |
|
29 |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 3
ok, latest stable version should be in default
You need to be logged in to leave comments.
Login now