Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.NET 9.0 locking fixes #25

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
<!-- Dependencies -->
<ItemGroup>
<PackageVersion Include="AspNet.Security.OAuth.GitHub" Version="8.1.0" />
<PackageVersion Include="Backport.System.Threading.Lock" Version="2.0.5" />
<PackageVersion Include="Blazorise" Version="$(BlazoriseVersion)" />
<PackageVersion Include="Blazorise.Bootstrap5" Version="$(BlazoriseVersion)" />
<PackageVersion Include="Blazorise.DataGrid" Version="$(BlazoriseVersion)" />
Expand Down
2 changes: 1 addition & 1 deletion samples/MeshRpc/Services/CounterStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ namespace Samples.MeshRpc.Services;

public static class CounterStorage
{
private static readonly object Lock = new();
private static readonly Lock Lock = new();
private static readonly Dictionary<int, MutableState<Counter>> States = new();

public static Counter Get(int key)
Expand Down
4 changes: 2 additions & 2 deletions samples/MiniRpc/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Runtime.Serialization;
using System.Runtime.Serialization;
using ActualLab.Fusion.Server;
using ActualLab.IO;
using ActualLab.Rpc;
Expand Down Expand Up @@ -103,7 +103,7 @@ public sealed partial record Chat_Post(

public class Chat : IChat
{
private readonly object _lock = new();
private readonly Lock _lock = new();
private List<string> _posts = new();

public virtual Task<List<string>> GetRecentMessages(CancellationToken cancellationToken = default)
Expand Down
2 changes: 1 addition & 1 deletion samples/MultiServerRpc/Service.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public sealed partial record Chat_Post(

public class Chat(ServerId serverId) : IChat
{
private readonly object _lock = new();
private readonly Lock _lock = new();
private readonly Dictionary<Symbol, List<string>> _chats = new();

private ServerId ServerId { get; } = serverId;
Expand Down
4 changes: 0 additions & 4 deletions src/ActualLab.CommandR/Operations/Operation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ namespace ActualLab.CommandR.Operations;

public class Operation : IHasUuid, IHasId<Symbol>
{
#if NET9_0_OR_GREATER
private readonly Lock _lock = new();
#else
private readonly object _lock = new();
#endif
Symbol IHasId<Symbol>.Id => Uuid;

public long? Index { get; set; }
Expand Down
4 changes: 4 additions & 0 deletions src/ActualLab.Core/ActualLab.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
<PackageReference Include="Ulid" />
<PackageReference Include="ZString" />
</ItemGroup>

<ItemGroup Condition="!$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net9.0'))">
<PackageReference Include="Backport.System.Threading.Lock" />
</ItemGroup>

<ItemGroup Condition="!$(TargetFramework.StartsWith('netstandard2.0'))">
<PackageReference Include="MemoryPack.Core" />
Expand Down
6 changes: 1 addition & 5 deletions src/ActualLab.Core/Async/ProcessorBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@ public abstract class ProcessorBase : IAsyncDisposable, IDisposable, IHasWhenDis
{
private volatile Task? _disposeTask;

#if NET9_0_OR_GREATER
protected Lock Lock { get; } = new();
#else
protected object Lock { get; } = new();
#endif
protected Lock Lock = new();
protected CancellationTokenSource StopTokenSource { get; }

public CancellationToken StopToken { get; }
Expand Down
4 changes: 0 additions & 4 deletions src/ActualLab.Core/Collections/MutableDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,7 @@ public class MutableDictionary<TKey, TValue>(ImmutableDictionary<TKey, TValue> i
: IMutableDictionary<TKey, TValue>
where TKey : notnull
{
#if NET9_0_OR_GREATER
private readonly Lock _lock = new();
#else
private readonly object _lock = new();
#endif
private volatile ImmutableDictionary<TKey, TValue> _items = items;

public ImmutableDictionary<TKey, TValue> Items {
Expand Down
4 changes: 0 additions & 4 deletions src/ActualLab.Core/Collections/MutableList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,7 @@ public interface IMutableList<T> : IReadOnlyMutableList<T>, IList<T>

public class MutableList<T>(ImmutableList<T> items) : IMutableList<T>
{
#if NET9_0_OR_GREATER
private readonly Lock _lock = new();
#else
private readonly object _lock = new();
#endif
private volatile ImmutableList<T> _items = items;

public ImmutableList<T> Items {
Expand Down
4 changes: 0 additions & 4 deletions src/ActualLab.Core/Collections/MutablePropertyBag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,7 @@ public interface IMutablePropertyBag : IReadOnlyPropertyBag
[Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptOut)]
public sealed partial class MutablePropertyBag : IMutablePropertyBag
{
#if NET9_0_OR_GREATER
private readonly Lock _lock = new();
#else
private readonly object _lock = new();
#endif
private PropertyBag _snapshot;

public event Action? Changed;
Expand Down
8 changes: 0 additions & 8 deletions src/ActualLab.Core/Diagnostics/Samplers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,7 @@ public static Sampler Random(double probability)
if (probability >= 1)
return Always;

#if NET9_0_OR_GREATER
Lock @lock = new();
#else
object @lock = new();
#endif
var rnd = new Random();
var maxIntBasedLimit = (int)((1d + int.MaxValue) * probability - 1);
var sampler = new Sampler(nameof(Random), probability, () => {
Expand Down Expand Up @@ -127,11 +123,7 @@ public static Sampler AlternativeRandom(double probability)
if (probability >= 1)
return Always;

#if NET9_0_OR_GREATER
Lock @lock = new();
#else
object @lock = new();
#endif
var rnd = new Random();
var stepSize = 1d / probability;
var maxIntBasedLimit = (int)((1d + int.MaxValue) * probability - 1);
Expand Down
2 changes: 1 addition & 1 deletion src/ActualLab.Core/Generators/RandomStringGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class RandomStringGenerator : Generator<string>, IDisposable

protected readonly RandomNumberGenerator Rng;
// ReSharper disable once InconsistentlySynchronizedField
protected object Lock => Rng;
protected Lock Lock = new();

public string Alphabet { get; }
public int Length { get; }
Expand Down
4 changes: 0 additions & 4 deletions src/ActualLab.Core/IO/ConsoleExt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@ namespace ActualLab.IO;

public static class ConsoleExt
{
#if NET9_0_OR_GREATER
private static readonly Lock Lock = new();
#else
private static readonly object Lock = new();
#endif
private static TaskScheduler? _scheduler;

public static TaskScheduler Scheduler {
Expand Down
3 changes: 2 additions & 1 deletion src/ActualLab.Core/LazySlim.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,15 @@ public static LazySlim<TArg0, TArg1, TValue> New<TArg0, TArg1, TValue>(

public sealed class LazySlim<TValue> : ILazySlim<TValue>
{
private readonly Lock _syncLock = new();
private Func<TValue>? _factory;
private TValue _value;

public TValue Value {
get {
// Double-check locking
if (_factory == null) return _value;
lock (this) {
lock (_syncLock) {
if (_factory == null) return _value;
_value = _factory.Invoke();
_factory = null;
Expand Down
4 changes: 0 additions & 4 deletions src/ActualLab.Core/Mathematics/PrimeSieve.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ namespace ActualLab.Mathematics;

public class PrimeSieve
{
#if NET9_0_OR_GREATER
private static readonly Lock Lock = new();
#else
private static readonly object Lock = new();
#endif
private static PrimeSieve? _instance;

private readonly int _limitSqrt;
Expand Down
4 changes: 0 additions & 4 deletions src/ActualLab.Core/Net/RetryDelayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ public class RetryDelayer : IRetryDelayer
private CancellationTokenSource _cancelDelaysCts = new();

private MomentClock? _clock;
#if NET9_0_OR_GREATER
protected readonly Lock Lock = new();
#else
protected readonly object Lock = new();
#endif

public Func<MomentClock> ClockProvider { get; init; } = static () => CpuClock.Instance;
public MomentClock Clock => _clock ??= ClockProvider.Invoke();
Expand Down
4 changes: 0 additions & 4 deletions src/ActualLab.Core/OS/HardwareInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@ namespace ActualLab.OS;
public static class HardwareInfo
{
private const int RefreshIntervalTicks = 30_000; // Tick = millisecond
#if NET9_0_OR_GREATER
private static readonly Lock Lock = new();
#else
private static readonly object Lock = new();
#endif
private static volatile int _processorCount;
private static volatile int _processorCountPo2;
private static volatile int _lastRefreshTicks =
Expand Down
4 changes: 0 additions & 4 deletions src/ActualLab.Core/Requirement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,7 @@ public abstract record Requirement<
{
private const string MustExistFieldOrPropertyName = "MustExist";
// ReSharper disable once StaticMemberInGenericType
#if NET9_0_OR_GREATER
private static readonly Lock MustExistLock = new();
#else
private static readonly object MustExistLock = new();
#endif
private static volatile Requirement<T>? _mustExist;

public static Requirement<T> MustExist {
Expand Down
4 changes: 0 additions & 4 deletions src/ActualLab.Core/StaticLog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ namespace ActualLab;

public static class StaticLog
{
#if NET9_0_OR_GREATER
private static readonly Lock Lock = new();
#else
private static readonly object Lock = new();
#endif
private static readonly ConcurrentDictionary<object, ILogger> Cache = new();
private static volatile ILoggerFactory _factory = NullLoggerFactory.Instance;

Expand Down
4 changes: 0 additions & 4 deletions src/ActualLab.Core/Time/TickSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ public sealed class TickSource(TimeSpan period)
// On other OSes it will be ~= t = N*NativeTimerPeriod so that t >= 15ms.
public static TickSource Default { get; set; } = new(TimeSpan.FromMilliseconds(15));

#if NET9_0_OR_GREATER
private readonly Lock _lock = new();
#else
private readonly object _lock = new();
#endif
private volatile Task _whenNextTick = Task.CompletedTask;

public TimeSpan Period { get; } = period > TimeSpan.Zero
Expand Down
4 changes: 0 additions & 4 deletions src/ActualLab.Core/Time/TimerSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,7 @@ public record TimerSetOptions
public sealed class TimerSet<TTimer> : WorkerBase
where TTimer : notnull
{
#if NET9_0_OR_GREATER
private readonly Lock _lock = new();
#else
private readonly object _lock = new();
#endif
private readonly Action<TTimer>? _fireHandler;
private readonly RadixHeapSet<TTimer> _timers = new(45);
private readonly Moment _start;
Expand Down
4 changes: 0 additions & 4 deletions src/ActualLab.Core/Trimming/CodeKeeper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ namespace ActualLab.Trimming;

public abstract class CodeKeeper
{
#if NET9_0_OR_GREATER
private static readonly Lock Lock = new();
#else
private static readonly object Lock = new();
#endif
private static readonly List<Action> Actions = new();
private static readonly HashSet<Action> ActionSet = new();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,7 @@ public Options()
}
};

#if NET9_0_OR_GREATER
private readonly Lock _lock = new();
#else
private readonly object _lock = new();
#endif
private Session? _session;
private volatile Task<AuthState> _authStateTask;
private volatile Task<AuthenticationState> _authenticationStateTask;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public interface IDbShardRegistry<TContext> : IDbShardRegistry;

public class DbShardRegistry<TContext> : IDbShardRegistry<TContext>, IDisposable
{
protected readonly object Lock = new();
protected readonly Lock Lock = new();
private readonly MutableState<ImmutableHashSet<DbShard>> _shards;
private readonly MutableState<ImmutableHashSet<DbShard>> _usedShards;
private readonly ComputedState<ImmutableHashSet<DbShard>> _eventProcessorShards;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,7 @@ public abstract class FlushingRemoteComputedCache : RemoteComputedCache
public MomentClock? Clock { get; init; }
}

#if NET9_0_OR_GREATER
protected readonly Lock Lock = new();
#else
protected readonly object Lock = new();
#endif
protected readonly MomentClock Clock;
protected Dictionary<RpcCacheKey, RpcCacheValue> FlushQueue = new();
protected Dictionary<RpcCacheKey, RpcCacheValue> FlushingQueue = new();
Expand Down Expand Up @@ -95,19 +91,19 @@ protected async Task DelayedFlush(TimeSpan? flushDelay, CancellationToken cancel
}
}

Monitor.Enter(Lock);
Lock.Enter();
try {
while (true) {
var flushingTask = FlushingTask;
if (flushingTask.IsCompleted)
break;

Monitor.Exit(Lock);
Lock.Exit();
try {
await flushingTask.SilentAwait(false);
}
finally {
Monitor.Enter(Lock);
Lock.Enter();
}
}
var flushingQueue = FlushingQueue = FlushQueue;
Expand All @@ -116,7 +112,7 @@ protected async Task DelayedFlush(TimeSpan? flushDelay, CancellationToken cancel
FlushTask = null;
}
finally {
Monitor.Exit(Lock);
Lock.Exit();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ namespace ActualLab.Fusion.Client.Caching;
public partial class RemoteComputedCache
{
private static Func<ComputeMethodInput, RpcPeer, Task>? _updateDelayer;
#if NET9_0_OR_GREATER
private static readonly Lock Lock = new();
#else
private static readonly object Lock = new();
#endif

public static Func<ComputeMethodInput, RpcPeer, Task>? UpdateDelayer {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down
5 changes: 1 addition & 4 deletions src/ActualLab.Fusion/Computed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,7 @@ public abstract partial class Computed(ComputedOptions options, ComputedInput in
// ReSharper disable once InconsistentNaming
private InvalidatedHandlerSet _invalidated;

protected object Lock {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => this;
}
protected Lock Lock = new();

protected ComputedFlags Flags {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down
4 changes: 0 additions & 4 deletions src/ActualLab.Fusion/ComputedRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,7 @@ public sealed record Options
public GCHandlePool? GCHandlePool { get; init; } = null;
}

#if NET9_0_OR_GREATER
private readonly Lock _lock = new();
#else
private readonly object _lock = new();
#endif
private readonly ConcurrentDictionary<ComputedInput, GCHandle> _storage;
private readonly GCHandlePool _gcHandlePool;
private StochasticCounter _opCounter;
Expand Down
2 changes: 1 addition & 1 deletion src/ActualLab.Fusion/ComputedSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class ComputedSource<T> : ComputedInput,
private ILogger? _log;

protected AsyncLock AsyncLock { get; }
protected object Lock => AsyncLock;
protected Lock Lock = new();
protected ILogger Log => _log ??= Services.LogFor(GetType());

public IServiceProvider Services { get; }
Expand Down
4 changes: 0 additions & 4 deletions src/ActualLab.Fusion/Configuration/FusionDefaults.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@ namespace ActualLab.Fusion;

public static class FusionDefaults
{
#if NET9_0_OR_GREATER
private static readonly Lock Lock = new();
#else
private static readonly object Lock = new();
#endif
private static FusionMode _mode;

public static FusionMode Mode {
Expand Down
Loading