diff --git a/readme.md b/readme.md index b189d7c..c24162f 100644 --- a/readme.md +++ b/readme.md @@ -69,5 +69,5 @@ Local experimentation shows further advantage to using `Environment.TickCount64` 2. Document the idea behind `ISystemClockTemporalContext`, without actually writing documentation # Remaining work -- [ ] Implement `IDisposable` and/or `IAsyncDisposable` on `ClockQuantizer` +- [X] Implement `IDisposable` and/or `IAsyncDisposable` on `ClockQuantizer` → [#6](https://github.com/edevoogd/ClockQuantization/pull/6) - [ ] Integrate this proposal in a [local fork](https://github.com/edevoogd/runtime) of Microsoft.Extensions.Caching.Memory as a PoC diff --git a/src/ClockQuantization.csproj b/src/ClockQuantization.csproj index 9faf376..a3ec1e7 100644 --- a/src/ClockQuantization.csproj +++ b/src/ClockQuantization.csproj @@ -1,4 +1,4 @@ - + Library @@ -13,7 +13,9 @@ + + \ No newline at end of file diff --git a/src/ClockQuantization.xml b/src/ClockQuantization.xml index 8a7d5f0..aca3ac3 100644 --- a/src/ClockQuantization.xml +++ b/src/ClockQuantization.xml @@ -163,6 +163,18 @@ the will pick up on external events, instead of relying on an internal metronome. + + + + + + + + + + + + Represents an interval within a 's temporal context. diff --git a/src/ClockQuantizer.cs b/src/ClockQuantizer.cs index 099696b..dcaffd8 100644 --- a/src/ClockQuantizer.cs +++ b/src/ClockQuantizer.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.CompilerServices; +using System.Threading.Tasks; namespace ClockQuantization { @@ -9,11 +10,11 @@ namespace ClockQuantization /// calls, as well as by and events. /// /// Under certain conditions, an advance operation may be incurred by calls. - public class ClockQuantizer //: IAsyncDisposable, IDisposable + public class ClockQuantizer : IAsyncDisposable, IDisposable { private readonly ISystemClock _clock; private Interval? _currentInterval; - private readonly System.Threading.Timer? _metronome; + private System.Threading.Timer? _metronome; #region Fields & properties @@ -320,5 +321,63 @@ private Interval CommitAdvance(AdvancePreparationInfo preparation) private void Context_MetronomeTicked(object? _, EventArgs __) => Advance(metronomic: true); private void Context_ClockAdjusted(object? _, EventArgs __) => Advance(metronomic: false); + + #region IAsyncDisposable/IDisposable + + /// + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + + /// + public async ValueTask DisposeAsync() + { + await DisposeAsyncCore(); + + Dispose(disposing: false); + GC.SuppressFinalize(this); + } + + /// + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + _metronome?.Dispose(); + } + + _metronome = null; + } + + /// + protected virtual async ValueTask DisposeAsyncCore() + { + if (_metronome is null) + { + goto done; + } + +#if NETSTANDARD2_1 || NETCOREAPP3_0 || NETCOREAPP3_1 || NET5_0 || NET5_0_OR_GREATER + if (_metronome is IAsyncDisposable asyncDisposable) + { + await asyncDisposable.DisposeAsync().ConfigureAwait(false); + goto finish; + } +#else + await default(ValueTask).ConfigureAwait(false); +#endif + _metronome!.Dispose(); + +#if NETSTANDARD2_1 || NETCOREAPP3_0 || NETCOREAPP3_1 || NET5_0 || NET5_0_OR_GREATER +finish: +#endif + _metronome = null; +done: + ; + } + +#endregion } -} \ No newline at end of file +}