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
