Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 3 additions & 1 deletion src/ClockQuantization.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Library</OutputType>
Expand All @@ -13,7 +13,9 @@
</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)|$(Platform)'=='netstandard2.0|AnyCPU'">
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="5.0.0" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="5.0.0" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
</ItemGroup>

</Project>
12 changes: 12 additions & 0 deletions src/ClockQuantization.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

65 changes: 62 additions & 3 deletions src/ClockQuantizer.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;

namespace ClockQuantization
{
Expand All @@ -9,11 +10,11 @@ namespace ClockQuantization
/// <see cref="Advance()"/> calls, as well as by <see cref="ISystemClockTemporalContext.ClockAdjusted"/> and <see cref="ISystemClockTemporalContext.MetronomeTicked"/> events.
/// </summary>
/// <remarks>Under certain conditions, an advance operation may be incurred by <see cref="EnsureInitializedExactClockOffsetSerialPosition(ref LazyClockOffsetSerialPosition, bool)"/> calls.</remarks>
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
Expand Down Expand Up @@ -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

/// <inheritdoc/>
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}

/// <inheritdoc/>
public async ValueTask DisposeAsync()
{
await DisposeAsyncCore();

Dispose(disposing: false);
GC.SuppressFinalize(this);
}

/// <inheritdoc/>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_metronome?.Dispose();
}

_metronome = null;
}

/// <inheritdoc/>
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
}
}
}