Auto status change to "Under Review"
@@ -24,7 +24,7 namespace Implab.Test.Mock { | |||||
24 | set; |
|
24 | set; | |
25 | } |
|
25 | } | |
26 |
|
26 | |||
27 |
public Action<bool |
|
27 | public Action<bool> MockDispose { | |
28 | get; |
|
28 | get; | |
29 | set; |
|
29 | set; | |
30 | } |
|
30 | } | |
@@ -42,10 +42,10 namespace Implab.Test.Mock { | |||||
42 | MockInit(); |
|
42 | MockInit(); | |
43 | } |
|
43 | } | |
44 |
|
44 | |||
45 |
protected override void Dispose(bool disposing |
|
45 | protected override void Dispose(bool disposing) { | |
46 | if (MockDispose != null) |
|
46 | if (MockDispose != null) | |
47 |
MockDispose(disposing |
|
47 | MockDispose(disposing); | |
48 |
base.Dispose(disposing |
|
48 | base.Dispose(disposing); | |
49 | } |
|
49 | } | |
50 | } |
|
50 | } | |
51 | } |
|
51 | } |
@@ -95,7 +95,7 namespace Implab.Test { | |||||
95 | var comp = new MockRunnableComponent(true); |
|
95 | var comp = new MockRunnableComponent(true); | |
96 |
|
96 | |||
97 | bool disposed = false; |
|
97 | bool disposed = false; | |
98 |
comp.MockDispose = (disposing |
|
98 | comp.MockDispose = (disposing) => { | |
99 | disposed = true; |
|
99 | disposed = true; | |
100 | }; |
|
100 | }; | |
101 |
|
101 | |||
@@ -115,7 +115,7 namespace Implab.Test { | |||||
115 | var comp = new MockRunnableComponent(true, true); |
|
115 | var comp = new MockRunnableComponent(true, true); | |
116 |
|
116 | |||
117 | bool disposed = false; |
|
117 | bool disposed = false; | |
118 |
comp.MockDispose = (disposing |
|
118 | comp.MockDispose = (disposing) => { | |
119 | disposed = true; |
|
119 | disposed = true; | |
120 | }; |
|
120 | }; | |
121 |
|
121 | |||
@@ -131,10 +131,8 namespace Implab.Test { | |||||
131 | var comp = new MockRunnableComponent(true, true); |
|
131 | var comp = new MockRunnableComponent(true, true); | |
132 |
|
132 | |||
133 | bool disposed = false; |
|
133 | bool disposed = false; | |
134 | Exception lastError = null; |
|
134 | comp.MockDispose = (disposing) => { | |
135 | comp.MockDispose = (disposing, error) => { |
|
|||
136 | disposed = true; |
|
135 | disposed = true; | |
137 | lastError = error; |
|
|||
138 | }; |
|
136 | }; | |
139 |
|
137 | |||
140 | comp.Start().Join(1000); |
|
138 | comp.Start().Join(1000); |
@@ -1,5 +1,6 | |||||
1 | using Implab.Diagnostics; |
|
1 | using Implab.Diagnostics; | |
2 | using System; |
|
2 | using System; | |
|
3 | using System.Diagnostics.CodeAnalysis; | |||
3 | using System.Threading; |
|
4 | using System.Threading; | |
4 |
|
5 | |||
5 | namespace Implab.Components { |
|
6 | namespace Implab.Components { | |
@@ -81,6 +82,7 namespace Implab.Components { | |||||
81 | } |
|
82 | } | |
82 | } |
|
83 | } | |
83 |
|
84 | |||
|
85 | [SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "Dipose(bool) and GC.SuppessFinalize are called")] | |||
84 | public void Dispose() { |
|
86 | public void Dispose() { | |
85 | if (Interlocked.Increment(ref m_disposed) == 1) { |
|
87 | if (Interlocked.Increment(ref m_disposed) == 1) { | |
86 | Dispose(true); |
|
88 | Dispose(true); |
@@ -1,14 +1,22 | |||||
1 | using System; |
|
1 | using System; | |
2 |
|
2 | |||
3 | namespace Implab.Components { |
|
3 | namespace Implab.Components { | |
4 | public interface IRunnable { |
|
4 | /// <summary> | |
|
5 | /// Interface for the component which performs a long running task. | |||
|
6 | /// </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 { | |||
5 | /// <summary> |
|
13 | /// <summary> | |
6 |
/// Starts this instance |
|
14 | /// Starts this instance | |
7 | /// </summary> |
|
15 | /// </summary> | |
8 | IPromise Start(); |
|
16 | IPromise Start(); | |
9 |
|
17 | |||
10 | /// <summary> |
|
18 | /// <summary> | |
11 | /// Stops this instance. After the instance is stopped it can't be started again, stopping should be treated as gracefull and async dispose. |
|
19 | /// 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. | |
12 | /// </summary> |
|
20 | /// </summary> | |
13 | IPromise Stop(); |
|
21 | IPromise Stop(); | |
14 |
|
22 |
@@ -144,11 +144,11 namespace Implab.Components { | |||||
144 | return base.OnStop(); |
|
144 | return base.OnStop(); | |
145 | } |
|
145 | } | |
146 |
|
146 | |||
147 |
protected override void Dispose(bool disposing |
|
147 | protected override void Dispose(bool disposing) { | |
148 | if (disposing) |
|
148 | if (disposing) | |
149 |
|
|
149 | m_timer.Dispose(); | |
150 |
|
150 | |||
151 |
base.Dispose(disposing |
|
151 | base.Dispose(disposing); | |
152 | } |
|
152 | } | |
153 | } |
|
153 | } | |
154 | } |
|
154 | } |
@@ -1,5 +1,6 | |||||
1 | using System; |
|
1 | using System; | |
2 |
|
2 | using System.Diagnostics.CodeAnalysis; | ||
|
3 | ||||
3 | namespace Implab.Components { |
|
4 | namespace Implab.Components { | |
4 | public abstract class RunnableComponent : IDisposable, IRunnable, IInitializable { |
|
5 | public abstract class RunnableComponent : IDisposable, IRunnable, IInitializable { | |
5 | enum Commands { |
|
6 | enum Commands { | |
@@ -333,30 +334,22 namespace Implab.Components { | |||||
333 | /// especially if <see cref="Stop"/> method is failed. Using this method insted of <see cref="Stop()"/> may |
|
334 | /// especially if <see cref="Stop"/> method is failed. Using this method insted of <see cref="Stop()"/> may | |
334 | /// lead to the data loss by the component. |
|
335 | /// lead to the data loss by the component. | |
335 | /// </para></remarks> |
|
336 | /// </para></remarks> | |
|
337 | [SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "Dipose(bool) and GC.SuppessFinalize are called")] | |||
336 | public void Dispose() { |
|
338 | public void Dispose() { | |
337 | IPromise pending; |
|
339 | IPromise pending; | |
338 |
|
340 | |||
339 | lock (m_stateMachine) { |
|
341 | lock (m_stateMachine) { | |
340 | if (m_stateMachine.State == ExecutionState.Disposed) |
|
342 | if (m_stateMachine.State == ExecutionState.Disposed) | |
341 | return; |
|
343 | return; | |
342 |
|
|
344 | Move(Commands.Dispose, null, null); | |
343 | } |
|
345 | } | |
344 |
|
346 | |||
345 | GC.SuppressFinalize(this); |
|
347 | GC.SuppressFinalize(this); | |
346 | if (pending != null) { |
|
348 | Dispose(true); | |
347 | pending.Cancel(); |
|
|||
348 | pending.Timeout(DisposeTimeout).On( |
|
|||
349 | () => Dispose(true, null), |
|
|||
350 | err => Dispose(true, err), |
|
|||
351 | reason => Dispose(true, new OperationCanceledException("The operation is cancelled", reason)) |
|
|||
352 | ); |
|
|||
353 | } else { |
|
|||
354 | Dispose(true, null); |
|
|||
355 | } |
|
|||
356 | } |
|
349 | } | |
357 |
|
350 | |||
358 | ~RunnableComponent() { |
|
351 | ~RunnableComponent() { | |
359 |
Dispose(false |
|
352 | Dispose(false); | |
360 | } |
|
353 | } | |
361 |
|
354 | |||
362 | #endregion |
|
355 | #endregion | |
@@ -365,8 +358,8 namespace Implab.Components { | |||||
365 | /// Releases all resources used by the component, called automatically, override this method to implement your cleanup. |
|
358 | /// Releases all resources used by the component, called automatically, override this method to implement your cleanup. | |
366 | /// </summary> |
|
359 | /// </summary> | |
367 | /// <param name="disposing">true if this method is called during normal dispose process.</param> |
|
360 | /// <param name="disposing">true if this method is called during normal dispose process.</param> | |
368 |
/// <param name=" |
|
361 | /// <param name="pending">The operation which is currenty pending</param> | |
369 |
protected virtual void Dispose(bool disposing |
|
362 | protected virtual void Dispose(bool disposing) { | |
370 |
|
363 | |||
371 | } |
|
364 | } | |
372 |
|
365 |
@@ -274,7 +274,7 namespace Implab.Formats.JSON { | |||||
274 |
|
274 | |||
275 | protected override void Dispose(bool disposing) { |
|
275 | protected override void Dispose(bool disposing) { | |
276 | if (disposing) |
|
276 | if (disposing) | |
277 |
|
|
277 | m_scanner.Dispose(); | |
278 | } |
|
278 | } | |
279 |
|
279 | |||
280 | /// <summary> |
|
280 | /// <summary> |
@@ -102,7 +102,7 namespace Implab.Formats.JSON { | |||||
102 |
|
102 | |||
103 | protected override void Dispose(bool disposing) { |
|
103 | protected override void Dispose(bool disposing) { | |
104 | if (disposing) |
|
104 | if (disposing) | |
105 |
|
|
105 | m_scanner.Dispose(); | |
106 | base.Dispose(disposing); |
|
106 | base.Dispose(disposing); | |
107 | } |
|
107 | } | |
108 | } |
|
108 | } |
@@ -120,8 +120,12 namespace Implab { | |||||
120 | } |
|
120 | } | |
121 |
|
121 | |||
122 | public static IPromise<T[]> PromiseAll<T>(this IEnumerable<IPromise<T>> that) { |
|
122 | public static IPromise<T[]> PromiseAll<T>(this IEnumerable<IPromise<T>> that) { | |
|
123 | return PromiseAll(that, null); | |||
|
124 | } | |||
|
125 | ||||
|
126 | public static IPromise<T[]> PromiseAll<T>(this IEnumerable<IPromise<T>> that, Action<T> cleanup) { | |||
123 | Safe.ArgumentNotNull(that, "that"); |
|
127 | Safe.ArgumentNotNull(that, "that"); | |
124 | return PromiseAll(that.ToList()); |
|
128 | return PromiseAll(that.ToList(), cleanup); | |
125 | } |
|
129 | } | |
126 |
|
130 | |||
127 | public static IPromise PromiseAll(this ICollection<IPromise> that) { |
|
131 | public static IPromise PromiseAll(this ICollection<IPromise> that) { | |
@@ -164,17 +168,35 namespace Implab { | |||||
164 | return medium; |
|
168 | return medium; | |
165 | } |
|
169 | } | |
166 |
|
170 | |||
167 | public static IPromise<T[]> PromiseAll<T>(this ICollection<IPromise<T>> that) { |
|
171 | public static IPromise<T[]> PromiseAll<T>(this ICollection<IPromise<T>> that) { | |
|
172 | return PromiseAll(that, null); | |||
|
173 | } | |||
|
174 | ||||
|
175 | /// <summary> | |||
|
176 | /// Creates a new promise which will be satisfied when all promises are satisfied. | |||
|
177 | /// </summary> | |||
|
178 | /// <typeparam name="T"></typeparam> | |||
|
179 | /// <param name="that"></param> | |||
|
180 | /// <param name="cleanup">A callback used to cleanup already resolved promises in case of an error</param> | |||
|
181 | /// <returns></returns> | |||
|
182 | public static IPromise<T[]> PromiseAll<T>(this ICollection<IPromise<T>> that, Action<T> cleanup) { | |||
168 | Safe.ArgumentNotNull(that, "that"); |
|
183 | Safe.ArgumentNotNull(that, "that"); | |
|
184 | ||||
|
185 | int count = that.Count; | |||
169 |
|
186 | |||
170 |
i |
|
187 | if (count == 0) | |
|
188 | return Promise<T[]>.FromResult(new T[0]); | |||
|
189 | ||||
171 | int errors = 0; |
|
190 | int errors = 0; | |
172 | var medium = new Promise<T[]>(); |
|
191 | var medium = new Promise<T[]>(); | |
173 | var results = new T[that.Count]; |
|
192 | var results = new T[that.Count]; | |
174 |
|
193 | |||
175 | medium.On(() => { |
|
194 | medium.On(() => { | |
176 | foreach (var p2 in that) |
|
195 | foreach (var p2 in that) { | |
177 | p2.Cancel(); |
|
196 | p2.Cancel(); | |
|
197 | if (cleanup != null) | |||
|
198 | p2.On(cleanup); | |||
|
199 | } | |||
178 | }, PromiseEventType.ErrorOrCancel); |
|
200 | }, PromiseEventType.ErrorOrCancel); | |
179 |
|
201 | |||
180 | int i = 0; |
|
202 | int i = 0; | |
@@ -414,6 +436,12 namespace Implab { | |||||
414 | return new PromiseAwaiter<T>(that); |
|
436 | return new PromiseAwaiter<T>(that); | |
415 | } |
|
437 | } | |
416 |
|
438 | |||
|
439 | public static PromiseAwaiter GetAwaiter(this IPromise that) { | |||
|
440 | Safe.ArgumentNotNull(that, "that"); | |||
|
441 | ||||
|
442 | return new PromiseAwaiter(that); | |||
|
443 | } | |||
|
444 | ||||
417 | #endif |
|
445 | #endif | |
418 | } |
|
446 | } | |
419 | } |
|
447 | } |
General Comments 3
ok, latest stable version should be in default
You need to be logged in to leave comments.
Login now