Skip to content

Adds support for threading lock in .NET 9 and C# 13 #319

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

Open
wants to merge 2 commits into
base: main
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
2 changes: 1 addition & 1 deletion src/R3.Avalonia/AvaloniaDispatcherFrameProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public sealed class AvaloniaDispatcherFrameProvider : FrameProvider, IDisposable
long frameCount;
readonly bool isDefaultFrameProvider = false;
FreeListCore<IFrameRunnerWorkItem> list;
readonly object gate = new object();
readonly Lock gate = new();
readonly DispatcherTimer timer;
EventHandler timerTick;

Expand Down
2 changes: 1 addition & 1 deletion src/R3.Avalonia/AvaloniaRenderingFrameProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class AvaloniaRenderingFrameProvider : FrameProvider, IDisposable
bool disposed;
long frameCount;
FreeListCore<IFrameRunnerWorkItem> list;
readonly object gate = new object();
readonly Lock gate = new();

Action<TimeSpan> messageLoop;

Expand Down
2 changes: 1 addition & 1 deletion src/R3.Avalonia/ObserveOnExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ sealed class _ObserveOnDispatcher : Observer<T>
readonly Observer<T> observer;
readonly Dispatcher dispatcher;
readonly DispatcherPriority? dispatcherPriority;
readonly object gate = new object();
readonly Lock gate = new();
SwapListCore<Notification<T>> list;
bool running;

Expand Down
2 changes: 1 addition & 1 deletion src/R3.Avalonia/R3.Avalonia.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFrameworks>netstandard2.0;netstandard2.1;net6.0;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>12</LangVersion>
<LangVersion>13</LangVersion>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>1701;1702;1591;1573</NoWarn>

Expand Down
2 changes: 1 addition & 1 deletion src/R3.Blazor/R3.Blazor.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<OutputType>Library</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>12</LangVersion>
<LangVersion>13</LangVersion>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>1701;1702;1591;1573</NoWarn>
<RootNamespace>R3</RootNamespace>
Expand Down
2 changes: 1 addition & 1 deletion src/R3.BlazorWebAssembly/R3.BlazorWebAssembly.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<OutputType>Library</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>12</LangVersion>
<LangVersion>13</LangVersion>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>1701;1702;1591;1573</NoWarn>
<RootNamespace>R3</RootNamespace>
Expand Down
1 change: 1 addition & 0 deletions src/R3.Godot/R3.Godot.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<NoWarn>1701;1702;1591;1573;8002;</NoWarn>
<!-- Currently no packable -->
<IsPackable>false</IsPackable>
<LangVersion>13</LangVersion>
</PropertyGroup>

<ItemGroup>
Expand Down
3 changes: 2 additions & 1 deletion src/R3.Godot/addons/R3.Godot/GodotFrameProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using R3.Collections;
using System;
using System.Runtime.CompilerServices;
using System.Threading;

namespace R3;

Expand All @@ -19,7 +20,7 @@ public class GodotFrameProvider : FrameProvider
public static readonly GodotFrameProvider PhysicsProcess = new GodotFrameProvider(PlayerLoopTiming.PhysicsProcess);

FreeListCore<IFrameRunnerWorkItem> list;
readonly object gate = new object();
readonly Lock gate = new();

PlayerLoopTiming PlayerLoopTiming { get; }

Expand Down
2 changes: 1 addition & 1 deletion src/R3.Godot/addons/R3.Godot/GodotTimeProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ enum RunningState
readonly TimerCallback callback;
readonly object? state;
readonly GodotFrameProvider frameProvider;
readonly object gate = new object();
readonly Lock gate = new();

TimeSpan dueTime;
TimeSpan period;
Expand Down
2 changes: 1 addition & 1 deletion src/R3.LogicLooper/LogicLooperFrameProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public sealed class LogicLooperFrameProvider : FrameProvider, IDisposable
Task loop;
internal long timestamp;
internal TimeSpan deltaTime;
readonly object gate = new object();
readonly Lock gate = new();

public LogicLooperFrameProvider(ILogicLooper looper)
{
Expand Down
2 changes: 1 addition & 1 deletion src/R3.LogicLooper/LogicLooperTimeProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ enum RunningState
readonly TimerCallback callback;
readonly object? state;
readonly LogicLooperFrameProvider frameProvider;
readonly object gate = new object();
readonly Lock gate = new();

TimeSpan dueTime;
TimeSpan period;
Expand Down
2 changes: 1 addition & 1 deletion src/R3.LogicLooper/R3.LogicLooper.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFrameworks>netstandard2.0;netstandard2.1;net6.0;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>12</LangVersion>
<LangVersion>13</LangVersion>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>1701;1702;1591;1573</NoWarn>

Expand Down
2 changes: 1 addition & 1 deletion src/R3.Maui/R3.Maui.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFrameworks>netstandard2.0;netstandard2.1;net6.0;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>12</LangVersion>
<LangVersion>13</LangVersion>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>1701;1702;1591;1573;CS8002</NoWarn>

Expand Down
2 changes: 1 addition & 1 deletion src/R3.MonoGame/R3.MonoGame.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<Nullable>enable</Nullable>
<LangVersion>12</LangVersion>
<LangVersion>13</LangVersion>

<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>1701;1702;1591;1573;CS8002</NoWarn>
Expand Down
1 change: 1 addition & 0 deletions src/R3.Stride/R3.Stride.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<PackageId>R3Extensions.Stride</PackageId>
<PackageTags>rx</PackageTags>
<Description>Stride Provider and Methods for R3.</Description>
<LangVersion>13</LangVersion>
</PropertyGroup>

<ItemGroup>
Expand Down
3 changes: 2 additions & 1 deletion src/R3.Stride/StrideFrameProvider.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using R3.Collections;
using Stride.Games;

Expand All @@ -8,7 +9,7 @@ namespace R3;
public sealed class StrideFrameProvider : FrameProvider
{
FreeListCore<IFrameRunnerWorkItem> list;
readonly object gate = new object();
readonly Lock gate = new();

internal StrongBox<double> Delta = default!; // set from Node before running process.

Expand Down
2 changes: 1 addition & 1 deletion src/R3.Stride/StrideTimeProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ enum RunningState
TimeSpan period;
bool isDisposed;
readonly StrideFrameProvider frameProvider;
readonly object gate = new object();
readonly Lock gate = new();
RunningState runningState;
double elapsed;

Expand Down
2 changes: 1 addition & 1 deletion src/R3.Uno/ObserveOnExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ sealed class _ObserveOnDispatcher : Observer<T>
readonly Observer<T> observer;
readonly CoreDispatcher dispatcher;
readonly CoreDispatcherPriority? dispatcherPriority;
readonly object gate = new object();
readonly Lock gate = new();
SwapListCore<Notification<T>> list;
bool running;

Expand Down
1 change: 1 addition & 0 deletions src/R3.Uno/R3.Uno.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<PackageId>R3Extensions.Uno</PackageId>
<PackageTags>rx</PackageTags>
<Description>Uno Provider and Methods for R3.</Description>
<LangVersion>13</LangVersion>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/R3.Uno/UnoDispatcherFrameProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public sealed class UnoRenderingFrameProvider : FrameProvider, IDisposable
bool disposed;
long frameCount;
FreeListCore<IFrameRunnerWorkItem> list;
readonly object gate = new object();
readonly Lock gate = new();

EventHandler<object> messageLoop;

Expand Down
2 changes: 1 addition & 1 deletion src/R3.WPF/ObserveOnExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ sealed class _ObserveOnDispatcher : Observer<T>
readonly Observer<T> observer;
readonly Dispatcher dispatcher;
readonly DispatcherPriority dispatcherPriority;
readonly object gate = new object();
readonly Lock gate = new();
SwapListCore<Notification<T>> list;
bool running;

Expand Down
2 changes: 1 addition & 1 deletion src/R3.WPF/R3.WPF.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFrameworks>net6.0-windows;net7.0-windows;net8.0-windows;net472;</TargetFrameworks>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
<LangVersion>12</LangVersion>
<LangVersion>13</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<EnableWindowsTargeting>true</EnableWindowsTargeting>

Expand Down
2 changes: 1 addition & 1 deletion src/R3.WPF/WpfRenderingFrameProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public sealed class WpfRenderingFrameProvider : FrameProvider, IDisposable
bool disposed;
long frameCount;
FreeListCore<IFrameRunnerWorkItem> list;
readonly object gate = new object();
readonly Lock gate = new();

EventHandler messageLoop;

Expand Down
4 changes: 2 additions & 2 deletions src/R3.WinForms/R3.WinForms.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFrameworks>net6.0-windows;net8.0-windows;net472</TargetFrameworks>
<UseWindowsForms>true</UseWindowsForms>
<LangVersion>12</LangVersion>
<LangVersion>13</LangVersion>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
<EnableWindowsTargeting>true</EnableWindowsTargeting>
Expand All @@ -16,7 +16,7 @@
<ItemGroup>
<None Include="../../Icon.png" Pack="true" PackagePath="/" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\R3\R3.csproj" />
</ItemGroup>
Expand Down
3 changes: 2 additions & 1 deletion src/R3.WinForms/WinFormsFrameProvider.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Threading;
using System.Windows.Forms;

using R3.Collections;
Expand All @@ -17,7 +18,7 @@ public sealed class WinFormsFrameProvider :
private bool disposed;
private long frameCount;
private FreeListCore<IFrameRunnerWorkItem> list;
private readonly object gate = new object();
private readonly Lock gate = new();
private readonly MessageHook filter;
private readonly MessageFilter? predicate;

Expand Down
1 change: 1 addition & 0 deletions src/R3.WinUI3/R3.WinUI3.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<PackageId>R3Extensions.WinUI3</PackageId>
<PackageTags>rx</PackageTags>
<Description>WinUI3 Provider and Methods for R3.</Description>
<LangVersion>13</LangVersion>
</PropertyGroup>

<ItemGroup>
Expand Down
3 changes: 2 additions & 1 deletion src/R3.WinUI3/WinUI3RenderingFrameProvider.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using R3.Collections;

namespace R3;
Expand All @@ -12,7 +13,7 @@ public sealed class WinUI3RenderingFrameProvider : FrameProvider, IDisposable
bool disposed;
long frameCount;
FreeListCore<IFrameRunnerWorkItem> list;
readonly object gate = new object();
readonly Lock gate = new();

EventHandler<object> messageLoop;

Expand Down
8 changes: 4 additions & 4 deletions src/R3/AwaitOperation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ internal abstract class AwaitOperationSwitchObserver<T> : Observer<T>
CancellationTokenSource cancellationTokenSource;
readonly bool configureAwait; // continueOnCapturedContext
readonly bool cancelOnCompleted;
protected readonly object gate = new object();
protected readonly Lock gate = new();
bool running;
bool completed;

Expand Down Expand Up @@ -292,7 +292,7 @@ internal abstract class AwaitOperationParallelObserver<T> : Observer<T>
readonly CancellationTokenSource cancellationTokenSource;
readonly bool configureAwait; // continueOnCapturedContext
readonly bool cancelOnCompleted;
protected readonly object gate = new object(); // need to use gate.
protected readonly Lock gate = new(); // need to use gate.

protected sealed override bool AutoDisposeOnCompleted => false; // disable auto-dispose
int runningCount = 0;
Expand Down Expand Up @@ -459,7 +459,7 @@ async void RunQueueWorker() // don't(can't) wait so use async void
internal abstract class AwaitOperationParallelConcurrentLimitObserver<T>(bool configureAwait, bool cancelOnCompleted, int maxConcurrent) : Observer<T>
{
readonly CancellationTokenSource cancellationTokenSource = new();
protected readonly object gate = new object(); // need to use gate.
protected readonly Lock gate = new(); // need to use gate.

protected sealed override bool AutoDisposeOnCompleted => false; // disable auto-dispose

Expand Down Expand Up @@ -555,7 +555,7 @@ internal abstract class AwaitOperationSequentialParallelConcurrentLimitObserver<
readonly bool configureAwait; // continueOnCapturedContext
readonly bool cancelOnCompleted;
readonly int maxConcurrent;
readonly object gate = new object();
readonly Lock gate = new();
readonly Channel<(T, ValueTask<TTaskValue>)> channel;
bool completed;
int runningCount;
Expand Down
19 changes: 14 additions & 5 deletions src/R3/Collections/FreeListCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,19 @@ namespace R3.Collections;
public struct FreeListCore<T>
where T : class
{
readonly Lock? lockGate;
readonly object gate;
T?[]? values = null;
int lastIndex;

public FreeListCore(Lock gate)
{
// don't create values at initialize
this.lockGate = gate;
this.gate = gate;
this.lastIndex = -1;
}

public FreeListCore(object gate)
{
// don't create values at initialize
Expand All @@ -30,7 +39,7 @@ public FreeListCore(object gate)

public void Add(T item, out int removeKey)
{
lock (gate)
lock (lockGate ?? gate)
{
ThrowHelper.ThrowObjectDisposedIf(IsDisposed, typeof(FreeListCore<T>));

Expand Down Expand Up @@ -63,7 +72,7 @@ public void Add(T item, out int removeKey)

public void Remove(int index)
{
lock (gate)
lock (lockGate ?? gate)
{
if (values == null) return;

Expand All @@ -83,7 +92,7 @@ public void Remove(int index)

public bool RemoveSlow(T value)
{
lock (gate)
lock (lockGate ?? gate)
{
if (values == null) return false;
if (lastIndex < 0) return false;
Expand All @@ -110,7 +119,7 @@ public bool RemoveSlow(T value)

public void Clear(bool removeArray)
{
lock (gate)
lock (lockGate ?? gate)
{
if (lastIndex >= 0)
{
Expand All @@ -129,7 +138,7 @@ public void Clear(bool removeArray)

public void Dispose()
{
lock (gate)
lock (lockGate ?? gate)
{
values = null;
lastIndex = -2; // -2 is disposed.
Expand Down
2 changes: 1 addition & 1 deletion src/R3/CompositeDisposable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace R3;
public sealed class CompositeDisposable : ICollection<IDisposable>, IDisposable
{
List<IDisposable?> list; // when removed, set null
readonly object gate = new object();
readonly Lock gate = new();
bool isDisposed;
int count;

Expand Down
2 changes: 1 addition & 1 deletion src/R3/Factories/Concat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ sealed class _Concat : IDisposable

public SerialDisposableCore disposable;
int id = 0;
readonly object gate = new object();
readonly Lock gate = new();

public _Concat(Observer<T> observer, IEnumerable<Observable<T>> sources)
{
Expand Down
Loading
Loading