diff --git a/src/R3.Avalonia/AvaloniaDispatcherFrameProvider.cs b/src/R3.Avalonia/AvaloniaDispatcherFrameProvider.cs index 61bc6034..1c942d8f 100644 --- a/src/R3.Avalonia/AvaloniaDispatcherFrameProvider.cs +++ b/src/R3.Avalonia/AvaloniaDispatcherFrameProvider.cs @@ -16,7 +16,7 @@ public sealed class AvaloniaDispatcherFrameProvider : FrameProvider, IDisposable long frameCount; readonly bool isDefaultFrameProvider = false; FreeListCore list; - readonly object gate = new object(); + readonly Lock gate = new(); readonly DispatcherTimer timer; EventHandler timerTick; diff --git a/src/R3.Avalonia/AvaloniaRenderingFrameProvider.cs b/src/R3.Avalonia/AvaloniaRenderingFrameProvider.cs index 198ea1e7..439932be 100644 --- a/src/R3.Avalonia/AvaloniaRenderingFrameProvider.cs +++ b/src/R3.Avalonia/AvaloniaRenderingFrameProvider.cs @@ -10,7 +10,7 @@ public class AvaloniaRenderingFrameProvider : FrameProvider, IDisposable bool disposed; long frameCount; FreeListCore list; - readonly object gate = new object(); + readonly Lock gate = new(); Action messageLoop; diff --git a/src/R3.Avalonia/ObserveOnExtensions.cs b/src/R3.Avalonia/ObserveOnExtensions.cs index b90cb5fa..3091a8ad 100644 --- a/src/R3.Avalonia/ObserveOnExtensions.cs +++ b/src/R3.Avalonia/ObserveOnExtensions.cs @@ -40,7 +40,7 @@ sealed class _ObserveOnDispatcher : Observer readonly Observer observer; readonly Dispatcher dispatcher; readonly DispatcherPriority? dispatcherPriority; - readonly object gate = new object(); + readonly Lock gate = new(); SwapListCore> list; bool running; diff --git a/src/R3.Avalonia/R3.Avalonia.csproj b/src/R3.Avalonia/R3.Avalonia.csproj index 1c4e3b03..a6095fd2 100644 --- a/src/R3.Avalonia/R3.Avalonia.csproj +++ b/src/R3.Avalonia/R3.Avalonia.csproj @@ -4,7 +4,7 @@ netstandard2.0;netstandard2.1;net6.0;net8.0 enable enable - 12 + 13 true 1701;1702;1591;1573 diff --git a/src/R3.Blazor/R3.Blazor.csproj b/src/R3.Blazor/R3.Blazor.csproj index 7f7f8ffa..7a61e7af 100644 --- a/src/R3.Blazor/R3.Blazor.csproj +++ b/src/R3.Blazor/R3.Blazor.csproj @@ -5,7 +5,7 @@ Library enable enable - 12 + 13 true 1701;1702;1591;1573 R3 diff --git a/src/R3.BlazorWebAssembly/R3.BlazorWebAssembly.csproj b/src/R3.BlazorWebAssembly/R3.BlazorWebAssembly.csproj index f43a749a..3946153a 100644 --- a/src/R3.BlazorWebAssembly/R3.BlazorWebAssembly.csproj +++ b/src/R3.BlazorWebAssembly/R3.BlazorWebAssembly.csproj @@ -5,7 +5,7 @@ Library enable enable - 12 + 13 true 1701;1702;1591;1573 R3 diff --git a/src/R3.Godot/R3.Godot.csproj b/src/R3.Godot/R3.Godot.csproj index 339bd60a..d774110c 100644 --- a/src/R3.Godot/R3.Godot.csproj +++ b/src/R3.Godot/R3.Godot.csproj @@ -7,6 +7,7 @@ 1701;1702;1591;1573;8002; false + 13 diff --git a/src/R3.Godot/addons/R3.Godot/GodotFrameProvider.cs b/src/R3.Godot/addons/R3.Godot/GodotFrameProvider.cs index 15e3e7a0..45a08cec 100644 --- a/src/R3.Godot/addons/R3.Godot/GodotFrameProvider.cs +++ b/src/R3.Godot/addons/R3.Godot/GodotFrameProvider.cs @@ -4,6 +4,7 @@ using R3.Collections; using System; using System.Runtime.CompilerServices; +using System.Threading; namespace R3; @@ -19,7 +20,7 @@ public class GodotFrameProvider : FrameProvider public static readonly GodotFrameProvider PhysicsProcess = new GodotFrameProvider(PlayerLoopTiming.PhysicsProcess); FreeListCore list; - readonly object gate = new object(); + readonly Lock gate = new(); PlayerLoopTiming PlayerLoopTiming { get; } diff --git a/src/R3.Godot/addons/R3.Godot/GodotTimeProvider.cs b/src/R3.Godot/addons/R3.Godot/GodotTimeProvider.cs index 3ef44a81..c2a12a75 100644 --- a/src/R3.Godot/addons/R3.Godot/GodotTimeProvider.cs +++ b/src/R3.Godot/addons/R3.Godot/GodotTimeProvider.cs @@ -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; diff --git a/src/R3.LogicLooper/LogicLooperFrameProvider.cs b/src/R3.LogicLooper/LogicLooperFrameProvider.cs index 3d36704d..b3dd15ff 100644 --- a/src/R3.LogicLooper/LogicLooperFrameProvider.cs +++ b/src/R3.LogicLooper/LogicLooperFrameProvider.cs @@ -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) { diff --git a/src/R3.LogicLooper/LogicLooperTimeProvider.cs b/src/R3.LogicLooper/LogicLooperTimeProvider.cs index 2fcb0f24..fac74bd3 100644 --- a/src/R3.LogicLooper/LogicLooperTimeProvider.cs +++ b/src/R3.LogicLooper/LogicLooperTimeProvider.cs @@ -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; diff --git a/src/R3.LogicLooper/R3.LogicLooper.csproj b/src/R3.LogicLooper/R3.LogicLooper.csproj index d2f72d25..ce620b96 100644 --- a/src/R3.LogicLooper/R3.LogicLooper.csproj +++ b/src/R3.LogicLooper/R3.LogicLooper.csproj @@ -4,7 +4,7 @@ netstandard2.0;netstandard2.1;net6.0;net8.0 enable enable - 12 + 13 true 1701;1702;1591;1573 diff --git a/src/R3.Maui/R3.Maui.csproj b/src/R3.Maui/R3.Maui.csproj index 8bffd069..b77a3af8 100644 --- a/src/R3.Maui/R3.Maui.csproj +++ b/src/R3.Maui/R3.Maui.csproj @@ -4,7 +4,7 @@ netstandard2.0;netstandard2.1;net6.0;net8.0 enable enable - 12 + 13 true 1701;1702;1591;1573;CS8002 diff --git a/src/R3.MonoGame/R3.MonoGame.csproj b/src/R3.MonoGame/R3.MonoGame.csproj index a0ddf9be..e0570716 100644 --- a/src/R3.MonoGame/R3.MonoGame.csproj +++ b/src/R3.MonoGame/R3.MonoGame.csproj @@ -3,7 +3,7 @@ net6.0;net8.0 enable - 12 + 13 true 1701;1702;1591;1573;CS8002 diff --git a/src/R3.Stride/R3.Stride.csproj b/src/R3.Stride/R3.Stride.csproj index 436acc4d..17b42f5a 100644 --- a/src/R3.Stride/R3.Stride.csproj +++ b/src/R3.Stride/R3.Stride.csproj @@ -9,6 +9,7 @@ R3Extensions.Stride rx Stride Provider and Methods for R3. + 13 diff --git a/src/R3.Stride/StrideFrameProvider.cs b/src/R3.Stride/StrideFrameProvider.cs index e06c7678..f800fa60 100644 --- a/src/R3.Stride/StrideFrameProvider.cs +++ b/src/R3.Stride/StrideFrameProvider.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.CompilerServices; +using System.Threading; using R3.Collections; using Stride.Games; @@ -8,7 +9,7 @@ namespace R3; public sealed class StrideFrameProvider : FrameProvider { FreeListCore list; - readonly object gate = new object(); + readonly Lock gate = new(); internal StrongBox Delta = default!; // set from Node before running process. diff --git a/src/R3.Stride/StrideTimeProvider.cs b/src/R3.Stride/StrideTimeProvider.cs index 6c32ed3c..88bbab3a 100644 --- a/src/R3.Stride/StrideTimeProvider.cs +++ b/src/R3.Stride/StrideTimeProvider.cs @@ -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; diff --git a/src/R3.Uno/ObserveOnExtensions.cs b/src/R3.Uno/ObserveOnExtensions.cs index aed0894f..3e549144 100644 --- a/src/R3.Uno/ObserveOnExtensions.cs +++ b/src/R3.Uno/ObserveOnExtensions.cs @@ -42,7 +42,7 @@ sealed class _ObserveOnDispatcher : Observer readonly Observer observer; readonly CoreDispatcher dispatcher; readonly CoreDispatcherPriority? dispatcherPriority; - readonly object gate = new object(); + readonly Lock gate = new(); SwapListCore> list; bool running; diff --git a/src/R3.Uno/R3.Uno.csproj b/src/R3.Uno/R3.Uno.csproj index 3e176a72..a8a51003 100644 --- a/src/R3.Uno/R3.Uno.csproj +++ b/src/R3.Uno/R3.Uno.csproj @@ -10,6 +10,7 @@ R3Extensions.Uno rx Uno Provider and Methods for R3. + 13 diff --git a/src/R3.Uno/UnoDispatcherFrameProvider.cs b/src/R3.Uno/UnoDispatcherFrameProvider.cs index b2502f2c..33c22ec3 100644 --- a/src/R3.Uno/UnoDispatcherFrameProvider.cs +++ b/src/R3.Uno/UnoDispatcherFrameProvider.cs @@ -12,7 +12,7 @@ public sealed class UnoRenderingFrameProvider : FrameProvider, IDisposable bool disposed; long frameCount; FreeListCore list; - readonly object gate = new object(); + readonly Lock gate = new(); EventHandler messageLoop; diff --git a/src/R3.WPF/ObserveOnExtensions.cs b/src/R3.WPF/ObserveOnExtensions.cs index 358e6704..328b5bac 100644 --- a/src/R3.WPF/ObserveOnExtensions.cs +++ b/src/R3.WPF/ObserveOnExtensions.cs @@ -40,7 +40,7 @@ sealed class _ObserveOnDispatcher : Observer readonly Observer observer; readonly Dispatcher dispatcher; readonly DispatcherPriority dispatcherPriority; - readonly object gate = new object(); + readonly Lock gate = new(); SwapListCore> list; bool running; diff --git a/src/R3.WPF/R3.WPF.csproj b/src/R3.WPF/R3.WPF.csproj index 43d4331c..45b3c0c9 100644 --- a/src/R3.WPF/R3.WPF.csproj +++ b/src/R3.WPF/R3.WPF.csproj @@ -4,7 +4,7 @@ net6.0-windows;net7.0-windows;net8.0-windows;net472; enable true - 12 + 13 enable true diff --git a/src/R3.WPF/WpfRenderingFrameProvider.cs b/src/R3.WPF/WpfRenderingFrameProvider.cs index b7ea6885..8de8fc6d 100644 --- a/src/R3.WPF/WpfRenderingFrameProvider.cs +++ b/src/R3.WPF/WpfRenderingFrameProvider.cs @@ -11,7 +11,7 @@ public sealed class WpfRenderingFrameProvider : FrameProvider, IDisposable bool disposed; long frameCount; FreeListCore list; - readonly object gate = new object(); + readonly Lock gate = new(); EventHandler messageLoop; diff --git a/src/R3.WinForms/R3.WinForms.csproj b/src/R3.WinForms/R3.WinForms.csproj index 8ad03cc3..c626873b 100644 --- a/src/R3.WinForms/R3.WinForms.csproj +++ b/src/R3.WinForms/R3.WinForms.csproj @@ -3,7 +3,7 @@ net6.0-windows;net8.0-windows;net472 true - 12 + 13 disable enable true @@ -16,7 +16,7 @@ - + diff --git a/src/R3.WinForms/WinFormsFrameProvider.cs b/src/R3.WinForms/WinFormsFrameProvider.cs index 5dbbf960..3fe1f33f 100644 --- a/src/R3.WinForms/WinFormsFrameProvider.cs +++ b/src/R3.WinForms/WinFormsFrameProvider.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Windows.Forms; using R3.Collections; @@ -17,7 +18,7 @@ public sealed class WinFormsFrameProvider : private bool disposed; private long frameCount; private FreeListCore list; - private readonly object gate = new object(); + private readonly Lock gate = new(); private readonly MessageHook filter; private readonly MessageFilter? predicate; diff --git a/src/R3.WinUI3/R3.WinUI3.csproj b/src/R3.WinUI3/R3.WinUI3.csproj index f1fd88f0..09032155 100644 --- a/src/R3.WinUI3/R3.WinUI3.csproj +++ b/src/R3.WinUI3/R3.WinUI3.csproj @@ -19,6 +19,7 @@ R3Extensions.WinUI3 rx WinUI3 Provider and Methods for R3. + 13 diff --git a/src/R3.WinUI3/WinUI3RenderingFrameProvider.cs b/src/R3.WinUI3/WinUI3RenderingFrameProvider.cs index 475e9485..bca993ad 100644 --- a/src/R3.WinUI3/WinUI3RenderingFrameProvider.cs +++ b/src/R3.WinUI3/WinUI3RenderingFrameProvider.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics.CodeAnalysis; +using System.Threading; using R3.Collections; namespace R3; @@ -12,7 +13,7 @@ public sealed class WinUI3RenderingFrameProvider : FrameProvider, IDisposable bool disposed; long frameCount; FreeListCore list; - readonly object gate = new object(); + readonly Lock gate = new(); EventHandler messageLoop; diff --git a/src/R3/AwaitOperation.cs b/src/R3/AwaitOperation.cs index d9235a68..7606d977 100644 --- a/src/R3/AwaitOperation.cs +++ b/src/R3/AwaitOperation.cs @@ -188,7 +188,7 @@ internal abstract class AwaitOperationSwitchObserver : Observer CancellationTokenSource cancellationTokenSource; readonly bool configureAwait; // continueOnCapturedContext readonly bool cancelOnCompleted; - protected readonly object gate = new object(); + protected readonly Lock gate = new(); bool running; bool completed; @@ -292,7 +292,7 @@ internal abstract class AwaitOperationParallelObserver : Observer 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; @@ -459,7 +459,7 @@ async void RunQueueWorker() // don't(can't) wait so use async void internal abstract class AwaitOperationParallelConcurrentLimitObserver(bool configureAwait, bool cancelOnCompleted, int maxConcurrent) : Observer { 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 @@ -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)> channel; bool completed; int runningCount; diff --git a/src/R3/Collections/FreeListCore.cs b/src/R3/Collections/FreeListCore.cs index 35a20559..76ada36b 100644 --- a/src/R3/Collections/FreeListCore.cs +++ b/src/R3/Collections/FreeListCore.cs @@ -7,10 +7,19 @@ namespace R3.Collections; public struct FreeListCore 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 @@ -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)); @@ -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; @@ -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; @@ -110,7 +119,7 @@ public bool RemoveSlow(T value) public void Clear(bool removeArray) { - lock (gate) + lock (lockGate ?? gate) { if (lastIndex >= 0) { @@ -129,7 +138,7 @@ public void Clear(bool removeArray) public void Dispose() { - lock (gate) + lock (lockGate ?? gate) { values = null; lastIndex = -2; // -2 is disposed. diff --git a/src/R3/CompositeDisposable.cs b/src/R3/CompositeDisposable.cs index 5ae64cf7..b0a4f31a 100644 --- a/src/R3/CompositeDisposable.cs +++ b/src/R3/CompositeDisposable.cs @@ -7,7 +7,7 @@ namespace R3; public sealed class CompositeDisposable : ICollection, IDisposable { List list; // when removed, set null - readonly object gate = new object(); + readonly Lock gate = new(); bool isDisposed; int count; diff --git a/src/R3/Factories/Concat.cs b/src/R3/Factories/Concat.cs index 07a5dbfe..9bf4aa70 100644 --- a/src/R3/Factories/Concat.cs +++ b/src/R3/Factories/Concat.cs @@ -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 observer, IEnumerable> sources) { diff --git a/src/R3/Factories/Merge.cs b/src/R3/Factories/Merge.cs index 7b306817..8de3a085 100644 --- a/src/R3/Factories/Merge.cs +++ b/src/R3/Factories/Merge.cs @@ -46,7 +46,7 @@ sealed class _Merge(Observer observer) : IDisposable { public Observer observer = observer; public SingleAssignmentDisposableCore disposable; - public readonly object gate = new object(); + public readonly Lock gate = new(); int sourceCount = -1; // not set yet. int completeCount; diff --git a/src/R3/FrameProvider.cs b/src/R3/FrameProvider.cs index 210069be..e83001ad 100644 --- a/src/R3/FrameProvider.cs +++ b/src/R3/FrameProvider.cs @@ -15,7 +15,7 @@ public interface IFrameRunnerWorkItem public sealed class FakeFrameProvider : FrameProvider { long frameCount; - readonly object gate = new object(); + readonly Lock gate = new(); FreeListCore list; public FakeFrameProvider() diff --git a/src/R3/Internal/Shims/LockPolyfill.cs b/src/R3/Internal/Shims/LockPolyfill.cs new file mode 100644 index 00000000..bf7b0eaa --- /dev/null +++ b/src/R3/Internal/Shims/LockPolyfill.cs @@ -0,0 +1,132 @@ +// This lock polyfill has been borrowed from the SimonCropp's excellent Polyfill project +// Original Implementation: https://github.com/SimonCropp/Polyfill/blob/49ebfe4ee1ce10b4872b83d4c5fdb53b9c808f4f/src/Polyfill/Lock.cs + +// Copyright (c) Simon Cropp +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + + +// +#pragma warning disable + +#nullable enable + +#if !NET9_0_OR_GREATER + +namespace System.Threading; + +using Diagnostics; +using Diagnostics.CodeAnalysis; +using Link = ComponentModel.DescriptionAttribute; + +/// +/// Provides a way to get mutual exclusion in regions of code between different threads. A lock may be held by one thread at +/// a time. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +//Link: https://learn.microsoft.com/en-us/dotnet/api/system.threading.lock +public class Lock +{ +#if NETCOREAPP || NETFRAMEWORK || NETSTANDARD + public bool IsHeldByCurrentThread => Monitor.IsEntered(this); +#endif + + /// + /// Enters the lock. Once the method returns, the calling thread would be the only thread that holds the lock. + /// + public void Enter() => Monitor.Enter(this); + + /// + /// Tries to enter the lock without waiting. If the lock is entered, the calling thread would be the only thread that + /// holds the lock. + /// + /// + /// true if the lock was entered, false otherwise. + /// + public bool TryEnter() => Monitor.TryEnter(this); + + /// + /// Tries to enter the lock, waiting for roughly the specified duration. If the lock is entered, the calling thread + /// would be the only thread that holds the lock. + /// + /// + /// The rough duration for which the method will wait if the lock is not available. The timeout is converted to a number + /// of milliseconds by casting of the timeout to an integer value. A value + /// representing 0 milliseconds specifies that the method should not wait, and a value representing + /// or -1 milliseconds specifies that the method should wait indefinitely + /// until the lock is entered. + /// + /// + /// true if the lock was entered, false otherwise. + /// + public bool TryEnter(TimeSpan timeout) => + Monitor.TryEnter(this, timeout); + + /// + /// Tries to enter the lock, waiting for roughly the specified duration. If the lock is entered, the calling thread + /// would be the only thread that holds the lock. + /// + /// + /// The rough duration in milliseconds for which the method will wait if the lock is not available. A value of + /// 0 specifies that the method should not wait, and a value of or + /// -1 specifies that the method should wait indefinitely until the lock is entered. + /// + /// + /// true if the lock was entered, false otherwise. + /// + public bool TryEnter(int millisecondsTimeout) => + TryEnter(TimeSpan.FromMilliseconds(millisecondsTimeout)); + + /// + /// Exits the lock. + /// + public void Exit() => Monitor.Exit(this); + + /// + /// Enters the lock and returns a that may be disposed to exit the lock. Once the method returns, + /// the calling thread would be the only thread that holds the lock. This method is intended to be used along with a + /// language construct that would automatically dispose the , such as with the C# using + /// statement. + /// + /// + /// A that may be disposed to exit the lock. + /// + public Scope EnterScope() + { + Enter(); + return new Scope(this); + } + + /// + /// A disposable structure that is returned by , which when disposed, exits the lock. + /// + public readonly ref struct Scope(Lock owner) + { + /// + /// Exits the lock. + /// + public void Dispose() => owner.Exit(); + } +} + +#else +using System.Runtime.CompilerServices; +[assembly: TypeForwardedTo(typeof(System.Threading.Lock))] +#endif diff --git a/src/R3/Operators/Chunk.cs b/src/R3/Operators/Chunk.cs index e037a4f5..0565ab52 100644 --- a/src/R3/Operators/Chunk.cs +++ b/src/R3/Operators/Chunk.cs @@ -247,7 +247,7 @@ sealed class _Chunk : Observer readonly int count; readonly TimeSpan timeSpan; readonly TimeProvider timeProvider; - readonly object gate = new object(); + readonly Lock gate = new(); ITimer? timer; T[] buffer; int index; diff --git a/src/R3/Operators/ChunkFrame.cs b/src/R3/Operators/ChunkFrame.cs index 462b10cb..76a9e50d 100644 --- a/src/R3/Operators/ChunkFrame.cs +++ b/src/R3/Operators/ChunkFrame.cs @@ -119,7 +119,7 @@ sealed class _Chunk : Observer, IFrameRunnerWorkItem readonly Observer observer; readonly int periodFrame; readonly int count; - readonly object gate = new object(); + readonly Lock gate = new(); readonly FrameProvider frameProvider; bool running; T[] buffer; diff --git a/src/R3/Operators/CombineLatest.cs b/src/R3/Operators/CombineLatest.cs index baa8cb76..e9cc175f 100644 --- a/src/R3/Operators/CombineLatest.cs +++ b/src/R3/Operators/CombineLatest.cs @@ -244,8 +244,7 @@ sealed class _CombineLatest : IDisposable readonly Func resultSelector; readonly CombineLatestObserver observer1; readonly CombineLatestObserver observer2; - - readonly object gate = new object(); + readonly Lock gate = new(); bool hasValueAll; int completedCount; @@ -376,8 +375,7 @@ sealed class _CombineLatest : IDisposable readonly CombineLatestObserver observer1; readonly CombineLatestObserver observer2; readonly CombineLatestObserver observer3; - - readonly object gate = new object(); + readonly Lock gate = new(); bool hasValueAll; int completedCount; @@ -516,8 +514,7 @@ sealed class _CombineLatest : IDisposable readonly CombineLatestObserver observer2; readonly CombineLatestObserver observer3; readonly CombineLatestObserver observer4; - - readonly object gate = new object(); + readonly Lock gate = new(); bool hasValueAll; int completedCount; @@ -664,8 +661,7 @@ sealed class _CombineLatest : IDisposable readonly CombineLatestObserver observer3; readonly CombineLatestObserver observer4; readonly CombineLatestObserver observer5; - - readonly object gate = new object(); + readonly Lock gate = new(); bool hasValueAll; int completedCount; @@ -820,8 +816,7 @@ sealed class _CombineLatest : IDisposable readonly CombineLatestObserver observer4; readonly CombineLatestObserver observer5; readonly CombineLatestObserver observer6; - - readonly object gate = new object(); + readonly Lock gate = new(); bool hasValueAll; int completedCount; @@ -984,8 +979,7 @@ sealed class _CombineLatest : IDisposable readonly CombineLatestObserver observer5; readonly CombineLatestObserver observer6; readonly CombineLatestObserver observer7; - - readonly object gate = new object(); + readonly Lock gate = new(); bool hasValueAll; int completedCount; @@ -1156,8 +1150,7 @@ sealed class _CombineLatest : IDisposable readonly CombineLatestObserver observer6; readonly CombineLatestObserver observer7; readonly CombineLatestObserver observer8; - - readonly object gate = new object(); + readonly Lock gate = new(); bool hasValueAll; int completedCount; @@ -1336,8 +1329,7 @@ sealed class _CombineLatest : IDisposable readonly CombineLatestObserver observer7; readonly CombineLatestObserver observer8; readonly CombineLatestObserver observer9; - - readonly object gate = new object(); + readonly Lock gate = new(); bool hasValueAll; int completedCount; @@ -1524,8 +1516,7 @@ sealed class _CombineLatest : IDisposable readonly CombineLatestObserver observer8; readonly CombineLatestObserver observer9; readonly CombineLatestObserver observer10; - - readonly object gate = new object(); + readonly Lock gate = new(); bool hasValueAll; int completedCount; @@ -1720,8 +1711,7 @@ sealed class _CombineLatest : IDisposable readonly CombineLatestObserver observer9; readonly CombineLatestObserver observer10; readonly CombineLatestObserver observer11; - - readonly object gate = new object(); + readonly Lock gate = new(); bool hasValueAll; int completedCount; @@ -1924,8 +1914,7 @@ sealed class _CombineLatest : IDisposable readonly CombineLatestObserver observer10; readonly CombineLatestObserver observer11; readonly CombineLatestObserver observer12; - - readonly object gate = new object(); + readonly Lock gate = new(); bool hasValueAll; int completedCount; @@ -2136,8 +2125,7 @@ sealed class _CombineLatest : IDisposable readonly CombineLatestObserver observer11; readonly CombineLatestObserver observer12; readonly CombineLatestObserver observer13; - - readonly object gate = new object(); + readonly Lock gate = new(); bool hasValueAll; int completedCount; @@ -2356,8 +2344,7 @@ sealed class _CombineLatest : IDisposable readonly CombineLatestObserver observer12; readonly CombineLatestObserver observer13; readonly CombineLatestObserver observer14; - - readonly object gate = new object(); + readonly Lock gate = new(); bool hasValueAll; int completedCount; @@ -2584,8 +2571,7 @@ sealed class _CombineLatest : IDisposable readonly CombineLatestObserver observer13; readonly CombineLatestObserver observer14; readonly CombineLatestObserver observer15; - - readonly object gate = new object(); + readonly Lock gate = new(); bool hasValueAll; int completedCount; diff --git a/src/R3/Operators/CombineLatest.tt b/src/R3/Operators/CombineLatest.tt index fc6bee20..a00999d2 100644 --- a/src/R3/Operators/CombineLatest.tt +++ b/src/R3/Operators/CombineLatest.tt @@ -56,8 +56,8 @@ internal sealed class CombineLatest<<#= generateT(i) #>, TResult>( readonly Func<<#= generateT(i) #>, TResult> resultSelector; <# for (var j = 1; j <= i; j++ ) { #> readonly CombineLatestObserver> observer<#= j #>; -<# } #> - readonly object gate = new object(); +<# } #> + readonly Lock gate = new(); bool hasValueAll; int completedCount; diff --git a/src/R3/Operators/Debounce.cs b/src/R3/Operators/Debounce.cs index 70007ab5..2d7c71bd 100644 --- a/src/R3/Operators/Debounce.cs +++ b/src/R3/Operators/Debounce.cs @@ -32,7 +32,7 @@ sealed class _Debounce : Observer readonly Observer observer; readonly TimeSpan timeSpan; readonly ITimer timer; - readonly object gate = new object(); + readonly Lock gate = new(); T? latestValue; bool hasvalue; int timerId; @@ -109,7 +109,7 @@ protected override IDisposable SubscribeCore(Observer observer) sealed class _Debounce(Observer observer, Func throttleDurationSelector, bool configureAwait) : Observer { - readonly object gate = new object(); + readonly Lock gate = new(); T? latestValue; bool hasValue; bool isRunning; diff --git a/src/R3/Operators/DebounceFrame.cs b/src/R3/Operators/DebounceFrame.cs index 4bfb56d9..0c6e5e30 100644 --- a/src/R3/Operators/DebounceFrame.cs +++ b/src/R3/Operators/DebounceFrame.cs @@ -25,7 +25,7 @@ sealed class _DebounceFrame : Observer, IFrameRunnerWorkItem { readonly Observer observer; readonly int frameCount; - readonly object gate = new object(); + readonly Lock gate = new(); readonly FrameProvider frameProvider; T? latestValue; bool hasvalue; diff --git a/src/R3/Operators/Multicast.cs b/src/R3/Operators/Multicast.cs index fd49d0a5..e853bc6f 100644 --- a/src/R3/Operators/Multicast.cs +++ b/src/R3/Operators/Multicast.cs @@ -77,7 +77,7 @@ public static Observable Share(this Observable source) internal sealed class Multicast(Observable source, ISubject subject) : ConnectableObservable { - readonly object gate = new object(); + readonly Lock gate = new(); Connection? connection; public override IDisposable Connect() diff --git a/src/R3/Operators/ObserveOn.cs b/src/R3/Operators/ObserveOn.cs index 1ff9b1ba..9d05d35e 100644 --- a/src/R3/Operators/ObserveOn.cs +++ b/src/R3/Operators/ObserveOn.cs @@ -54,7 +54,7 @@ sealed class _ObserveOn : Observer readonly Observer observer; readonly SynchronizationContext synchronizationContext; - readonly object gate = new object(); + readonly Lock gate = new(); SwapListCore> list; bool running; @@ -413,7 +413,7 @@ internal sealed class _ObserveOn : Observer, IFrameRunnerWorkItem { readonly Observer observer; readonly FrameProvider frameProvider; - readonly object gate = new object(); + readonly Lock gate = new(); SwapListCore> list; bool running; diff --git a/src/R3/Operators/RefCount.cs b/src/R3/Operators/RefCount.cs index f022a984..54814c1f 100644 --- a/src/R3/Operators/RefCount.cs +++ b/src/R3/Operators/RefCount.cs @@ -10,7 +10,7 @@ public static Observable RefCount(this ConnectableObservable source) internal sealed class RefCount(ConnectableObservable source) : Observable { - readonly object gate = new object(); + readonly Lock gate = new(); int refCount = 0; IDisposable? connection; diff --git a/src/R3/Operators/SelectMany.cs b/src/R3/Operators/SelectMany.cs index 658a1ad6..b78f4641 100644 --- a/src/R3/Operators/SelectMany.cs +++ b/src/R3/Operators/SelectMany.cs @@ -40,7 +40,7 @@ sealed class _SelectMany(Observer observer, Func> collectionSelector = collectionSelector; readonly Func resultSelector = resultSelector; readonly CompositeDisposable compositeDisposable = new(); - readonly object gate = new object(); + readonly Lock gate = new(); bool isStopped; protected override bool AutoDisposeOnCompleted => false; @@ -161,7 +161,7 @@ sealed class _SelectMany(Observer observer, Func> collectionSelector = collectionSelector; readonly Func resultSelector = resultSelector; readonly CompositeDisposable compositeDisposable = new(); - readonly object gate = new object(); + readonly Lock gate = new(); bool isStopped; int index = 0; diff --git a/src/R3/Operators/Switch.cs b/src/R3/Operators/Switch.cs index 7ea84f60..507502dc 100644 --- a/src/R3/Operators/Switch.cs +++ b/src/R3/Operators/Switch.cs @@ -18,7 +18,7 @@ protected override IDisposable SubscribeCore(Observer observer) sealed class _Switch(Observer observer) : Observer> { public Observer observer = observer; - public readonly object gate = new object(); + public readonly Lock gate = new(); SerialDisposableCore subscription; public ulong id; diff --git a/src/R3/Operators/Take.cs b/src/R3/Operators/Take.cs index 468ece45..49aeb324 100644 --- a/src/R3/Operators/Take.cs +++ b/src/R3/Operators/Take.cs @@ -88,7 +88,7 @@ sealed class _TakeTime : Observer, IDisposable readonly Observer observer; readonly ITimer timer; - readonly object gate = new object(); + readonly Lock gate = new(); public _TakeTime(Observer observer, TimeSpan duration, TimeProvider timeProvider) { @@ -145,7 +145,7 @@ sealed class _TakeFrame : Observer, IDisposable, IFrameRunnerWorkItem { readonly Observer observer; long remaining; - readonly object gate = new object(); + readonly Lock gate = new(); public _TakeFrame(Observer observer, int frameCount, FrameProvider frameProvider) { diff --git a/src/R3/Operators/TakeLast.cs b/src/R3/Operators/TakeLast.cs index 0f5c5f57..ca418150 100644 --- a/src/R3/Operators/TakeLast.cs +++ b/src/R3/Operators/TakeLast.cs @@ -106,7 +106,7 @@ protected override IDisposable SubscribeCore(Observer observer) sealed class _TakeLastTime : Observer, IDisposable { readonly Observer observer; - readonly object gate = new object(); + readonly Lock gate = new(); readonly Queue<(long timestamp, T value)> queue = new(); readonly TimeSpan duration; readonly TimeProvider timeProvider; @@ -188,7 +188,7 @@ protected override IDisposable SubscribeCore(Observer observer) sealed class _TakeLastFrame : Observer, IDisposable { readonly Observer observer; - readonly object gate = new object(); + readonly Lock gate = new(); readonly Queue<(long frameCount, T value)> queue = new(); readonly int frameCount; readonly FrameProvider frameProvider; diff --git a/src/R3/Operators/ThrottleFirst.cs b/src/R3/Operators/ThrottleFirst.cs index 36d237b4..ce852135 100644 --- a/src/R3/Operators/ThrottleFirst.cs +++ b/src/R3/Operators/ThrottleFirst.cs @@ -37,7 +37,7 @@ sealed class _ThrottleFirst : Observer readonly Observer observer; readonly ITimer timer; readonly TimeSpan timeSpan; - readonly object gate = new object(); + readonly Lock gate = new(); bool closing; public _ThrottleFirst(Observer observer, TimeSpan timeSpan, TimeProvider timeProvider) @@ -95,7 +95,7 @@ protected override IDisposable SubscribeCore(Observer observer) sealed class _ThrottleFirst(Observer observer, Func sampler, bool configureAwait) : Observer { - readonly object gate = new object(); + readonly Lock gate = new(); readonly CancellationTokenSource cancellationTokenSource = new(); bool closing; @@ -163,7 +163,7 @@ protected override IDisposable SubscribeCore(Observer observer) sealed class _ThrottleFirst : Observer { readonly Observer observer; - readonly object gate = new object(); + readonly Lock gate = new(); readonly IDisposable samplerSubscription; bool closing; diff --git a/src/R3/Operators/ThrottleFirstFrame.cs b/src/R3/Operators/ThrottleFirstFrame.cs index 5cd92b35..9a2b8f65 100644 --- a/src/R3/Operators/ThrottleFirstFrame.cs +++ b/src/R3/Operators/ThrottleFirstFrame.cs @@ -26,7 +26,7 @@ sealed class _ThrottleFirstFrame : Observer, IFrameRunnerWorkItem readonly Observer observer; readonly int frameCount; readonly FrameProvider frameProvider; - readonly object gate = new object(); + readonly Lock gate = new(); int currentFrame; bool closing; diff --git a/src/R3/Operators/ThrottleFirstLast.cs b/src/R3/Operators/ThrottleFirstLast.cs index 0fdacb13..15fe8fa1 100644 --- a/src/R3/Operators/ThrottleFirstLast.cs +++ b/src/R3/Operators/ThrottleFirstLast.cs @@ -37,7 +37,7 @@ sealed class _ThrottleFirstLast : Observer readonly Observer observer; readonly TimeSpan interval; readonly ITimer timer; - readonly object gate = new object(); + readonly Lock gate = new(); T? lastValue; bool hasValue; bool timerIsRunning; @@ -109,7 +109,7 @@ protected override IDisposable SubscribeCore(Observer observer) sealed class _ThrottleFirstLast(Observer observer, Func sampler, bool configureAwait) : Observer { - readonly object gate = new object(); + readonly Lock gate = new(); readonly CancellationTokenSource cancellationTokenSource = new(); T? lastValue; bool hasValue; @@ -191,7 +191,7 @@ protected override IDisposable SubscribeCore(Observer observer) sealed class _ThrottleFirstLast : Observer { readonly Observer observer; - readonly object gate = new object(); + readonly Lock gate = new(); readonly IDisposable samplerSubscription; T? lastValue; bool hasValue; diff --git a/src/R3/Operators/ThrottleFirstLastFrame.cs b/src/R3/Operators/ThrottleFirstLastFrame.cs index a1edaca3..4d6de6d5 100644 --- a/src/R3/Operators/ThrottleFirstLastFrame.cs +++ b/src/R3/Operators/ThrottleFirstLastFrame.cs @@ -25,7 +25,7 @@ sealed class _ThrottleFirstLastFrame : Observer, IFrameRunnerWorkItem readonly Observer observer; readonly FrameProvider frameProvider; readonly int frameCount; - readonly object gate = new object(); + readonly Lock gate = new(); T? lastValue; bool hasValue; int currentFrame; diff --git a/src/R3/Operators/ThrottleLast.cs b/src/R3/Operators/ThrottleLast.cs index 5c84e00f..0bd14ab8 100644 --- a/src/R3/Operators/ThrottleLast.cs +++ b/src/R3/Operators/ThrottleLast.cs @@ -37,7 +37,7 @@ sealed class _ThrottleLast : Observer readonly Observer observer; readonly TimeSpan interval; readonly ITimer timer; - readonly object gate = new object(); + readonly Lock gate = new(); T? lastValue; bool hasValue; @@ -102,7 +102,7 @@ protected override IDisposable SubscribeCore(Observer observer) sealed class _ThrottleLast(Observer observer, Func sampler, bool configureAwait) : Observer { - readonly object gate = new object(); + readonly Lock gate = new(); readonly CancellationTokenSource cancellationTokenSource = new(); T? lastValue; bool isRunning; @@ -173,7 +173,7 @@ protected override IDisposable SubscribeCore(Observer observer) sealed class _ThrottleLast : Observer { readonly Observer observer; - readonly object gate = new object(); + readonly Lock gate = new(); readonly IDisposable samplerSubscription; T? lastValue; bool hasValue; diff --git a/src/R3/Operators/ThrottleLastFrame.cs b/src/R3/Operators/ThrottleLastFrame.cs index 7ec9b658..6173b0d0 100644 --- a/src/R3/Operators/ThrottleLastFrame.cs +++ b/src/R3/Operators/ThrottleLastFrame.cs @@ -27,7 +27,7 @@ sealed class _ThrottleLastFrame : Observer, IFrameRunnerWorkItem readonly Observer observer; readonly FrameProvider frameProvider; readonly int frameCount; - readonly object gate = new object(); + readonly Lock gate = new(); T? lastValue; int currentFrame; bool running; diff --git a/src/R3/Operators/Timeout.cs b/src/R3/Operators/Timeout.cs index cdbcc518..cc371eab 100644 --- a/src/R3/Operators/Timeout.cs +++ b/src/R3/Operators/Timeout.cs @@ -27,7 +27,7 @@ sealed class _Timeout : Observer readonly Observer observer; readonly TimeSpan timeSpan; readonly ITimer timer; - readonly object gate = new object(); + readonly Lock gate = new(); int timerId; public _Timeout(Observer observer, TimeSpan timeSpan, TimeProvider timeProvider) diff --git a/src/R3/Operators/TimeoutFrame.cs b/src/R3/Operators/TimeoutFrame.cs index 16c6072f..44bbb65b 100644 --- a/src/R3/Operators/TimeoutFrame.cs +++ b/src/R3/Operators/TimeoutFrame.cs @@ -25,7 +25,7 @@ sealed class _TimeoutFrame : Observer, IFrameRunnerWorkItem readonly Observer observer; readonly FrameProvider frameProvider; readonly int periodFrame; - readonly object gate = new object(); + readonly Lock gate = new(); int currentFrame; bool running; diff --git a/src/R3/Operators/Zip.cs b/src/R3/Operators/Zip.cs index c03f50d7..71fc16df 100644 --- a/src/R3/Operators/Zip.cs +++ b/src/R3/Operators/Zip.cs @@ -239,8 +239,7 @@ sealed class _Zip : IDisposable readonly Func resultSelector; readonly ZipObserver observer1; readonly ZipObserver observer2; - - readonly object gate = new object(); + readonly Lock gate = new(); public _Zip( Observer observer, @@ -368,8 +367,7 @@ sealed class _Zip : IDisposable readonly ZipObserver observer1; readonly ZipObserver observer2; readonly ZipObserver observer3; - - readonly object gate = new object(); + readonly Lock gate = new(); public _Zip( Observer observer, @@ -505,8 +503,7 @@ sealed class _Zip : IDisposable readonly ZipObserver observer2; readonly ZipObserver observer3; readonly ZipObserver observer4; - - readonly object gate = new object(); + readonly Lock gate = new(); public _Zip( Observer observer, @@ -650,8 +647,7 @@ sealed class _Zip : IDisposable readonly ZipObserver observer3; readonly ZipObserver observer4; readonly ZipObserver observer5; - - readonly object gate = new object(); + readonly Lock gate = new(); public _Zip( Observer observer, @@ -803,8 +799,7 @@ sealed class _Zip : IDisposable readonly ZipObserver observer4; readonly ZipObserver observer5; readonly ZipObserver observer6; - - readonly object gate = new object(); + readonly Lock gate = new(); public _Zip( Observer observer, @@ -964,8 +959,7 @@ sealed class _Zip : IDisposable readonly ZipObserver observer5; readonly ZipObserver observer6; readonly ZipObserver observer7; - - readonly object gate = new object(); + readonly Lock gate = new(); public _Zip( Observer observer, @@ -1133,8 +1127,7 @@ sealed class _Zip : IDisposable readonly ZipObserver observer6; readonly ZipObserver observer7; readonly ZipObserver observer8; - - readonly object gate = new object(); + readonly Lock gate = new(); public _Zip( Observer observer, @@ -1310,8 +1303,7 @@ sealed class _Zip : IDisposable readonly ZipObserver observer7; readonly ZipObserver observer8; readonly ZipObserver observer9; - - readonly object gate = new object(); + readonly Lock gate = new(); public _Zip( Observer observer, @@ -1495,8 +1487,7 @@ sealed class _Zip : IDisposable readonly ZipObserver observer8; readonly ZipObserver observer9; readonly ZipObserver observer10; - - readonly object gate = new object(); + readonly Lock gate = new(); public _Zip( Observer observer, @@ -1688,8 +1679,7 @@ sealed class _Zip : IDisposable readonly ZipObserver observer9; readonly ZipObserver observer10; readonly ZipObserver observer11; - - readonly object gate = new object(); + readonly Lock gate = new(); public _Zip( Observer observer, @@ -1889,8 +1879,7 @@ sealed class _Zip : IDisposable readonly ZipObserver observer10; readonly ZipObserver observer11; readonly ZipObserver observer12; - - readonly object gate = new object(); + readonly Lock gate = new(); public _Zip( Observer observer, @@ -2098,8 +2087,7 @@ sealed class _Zip : IDisposable readonly ZipObserver observer11; readonly ZipObserver observer12; readonly ZipObserver observer13; - - readonly object gate = new object(); + readonly Lock gate = new(); public _Zip( Observer observer, @@ -2315,8 +2303,7 @@ sealed class _Zip : IDisposable readonly ZipObserver observer12; readonly ZipObserver observer13; readonly ZipObserver observer14; - - readonly object gate = new object(); + readonly Lock gate = new(); public _Zip( Observer observer, @@ -2540,8 +2527,7 @@ sealed class _Zip : IDisposable readonly ZipObserver observer13; readonly ZipObserver observer14; readonly ZipObserver observer15; - - readonly object gate = new object(); + readonly Lock gate = new(); public _Zip( Observer observer, diff --git a/src/R3/Operators/Zip.tt b/src/R3/Operators/Zip.tt index 9e2287eb..c5f29f0d 100644 --- a/src/R3/Operators/Zip.tt +++ b/src/R3/Operators/Zip.tt @@ -53,8 +53,8 @@ internal sealed class Zip<<#= generateT(i) #>, TResult>( readonly Func<<#= generateT(i) #>, TResult> resultSelector; <# for (var j = 1; j <= i; j++ ) { #> readonly ZipObserver> observer<#= j #>; -<# } #> - readonly object gate = new object(); +<# } #> + readonly Lock gate = new(); public _Zip( Observer observer, diff --git a/src/R3/Operators/ZipLatest.cs b/src/R3/Operators/ZipLatest.cs index ba762aea..c7ecd71d 100644 --- a/src/R3/Operators/ZipLatest.cs +++ b/src/R3/Operators/ZipLatest.cs @@ -239,8 +239,7 @@ sealed class _ZipLatest : IDisposable readonly Func resultSelector; readonly ZipLatestObserver observer1; readonly ZipLatestObserver observer2; - - readonly object gate = new object(); + readonly Lock gate = new(); public _ZipLatest( Observer observer, @@ -277,7 +276,7 @@ public void TryPublishOnNext() { var result = resultSelector(observer1.GetValue(), observer2.GetValue()); observer.OnNext(result); - + if (observer1.IsCompleted || observer2.IsCompleted) { observer.OnCompleted(); @@ -371,8 +370,7 @@ sealed class _ZipLatest : IDisposable readonly ZipLatestObserver observer1; readonly ZipLatestObserver observer2; readonly ZipLatestObserver observer3; - - readonly object gate = new object(); + readonly Lock gate = new(); public _ZipLatest( Observer observer, @@ -413,7 +411,7 @@ public void TryPublishOnNext() { var result = resultSelector(observer1.GetValue(), observer2.GetValue(), observer3.GetValue()); observer.OnNext(result); - + if (observer1.IsCompleted || observer2.IsCompleted || observer3.IsCompleted) { observer.OnCompleted(); @@ -511,8 +509,7 @@ sealed class _ZipLatest : IDisposable readonly ZipLatestObserver observer2; readonly ZipLatestObserver observer3; readonly ZipLatestObserver observer4; - - readonly object gate = new object(); + readonly Lock gate = new(); public _ZipLatest( Observer observer, @@ -557,7 +554,7 @@ public void TryPublishOnNext() { var result = resultSelector(observer1.GetValue(), observer2.GetValue(), observer3.GetValue(), observer4.GetValue()); observer.OnNext(result); - + if (observer1.IsCompleted || observer2.IsCompleted || observer3.IsCompleted || observer4.IsCompleted) { observer.OnCompleted(); @@ -659,8 +656,7 @@ sealed class _ZipLatest : IDisposable readonly ZipLatestObserver observer3; readonly ZipLatestObserver observer4; readonly ZipLatestObserver observer5; - - readonly object gate = new object(); + readonly Lock gate = new(); public _ZipLatest( Observer observer, @@ -709,7 +705,7 @@ public void TryPublishOnNext() { var result = resultSelector(observer1.GetValue(), observer2.GetValue(), observer3.GetValue(), observer4.GetValue(), observer5.GetValue()); observer.OnNext(result); - + if (observer1.IsCompleted || observer2.IsCompleted || observer3.IsCompleted || observer4.IsCompleted || observer5.IsCompleted) { observer.OnCompleted(); @@ -815,8 +811,7 @@ sealed class _ZipLatest : IDisposable readonly ZipLatestObserver observer4; readonly ZipLatestObserver observer5; readonly ZipLatestObserver observer6; - - readonly object gate = new object(); + readonly Lock gate = new(); public _ZipLatest( Observer observer, @@ -869,7 +864,7 @@ public void TryPublishOnNext() { var result = resultSelector(observer1.GetValue(), observer2.GetValue(), observer3.GetValue(), observer4.GetValue(), observer5.GetValue(), observer6.GetValue()); observer.OnNext(result); - + if (observer1.IsCompleted || observer2.IsCompleted || observer3.IsCompleted || observer4.IsCompleted || observer5.IsCompleted || observer6.IsCompleted) { observer.OnCompleted(); @@ -979,8 +974,7 @@ sealed class _ZipLatest : IDisposable readonly ZipLatestObserver observer5; readonly ZipLatestObserver observer6; readonly ZipLatestObserver observer7; - - readonly object gate = new object(); + readonly Lock gate = new(); public _ZipLatest( Observer observer, @@ -1037,7 +1031,7 @@ public void TryPublishOnNext() { var result = resultSelector(observer1.GetValue(), observer2.GetValue(), observer3.GetValue(), observer4.GetValue(), observer5.GetValue(), observer6.GetValue(), observer7.GetValue()); observer.OnNext(result); - + if (observer1.IsCompleted || observer2.IsCompleted || observer3.IsCompleted || observer4.IsCompleted || observer5.IsCompleted || observer6.IsCompleted || observer7.IsCompleted) { observer.OnCompleted(); @@ -1151,8 +1145,7 @@ sealed class _ZipLatest : IDisposable readonly ZipLatestObserver observer6; readonly ZipLatestObserver observer7; readonly ZipLatestObserver observer8; - - readonly object gate = new object(); + readonly Lock gate = new(); public _ZipLatest( Observer observer, @@ -1213,7 +1206,7 @@ public void TryPublishOnNext() { var result = resultSelector(observer1.GetValue(), observer2.GetValue(), observer3.GetValue(), observer4.GetValue(), observer5.GetValue(), observer6.GetValue(), observer7.GetValue(), observer8.GetValue()); observer.OnNext(result); - + if (observer1.IsCompleted || observer2.IsCompleted || observer3.IsCompleted || observer4.IsCompleted || observer5.IsCompleted || observer6.IsCompleted || observer7.IsCompleted || observer8.IsCompleted) { observer.OnCompleted(); @@ -1331,8 +1324,7 @@ sealed class _ZipLatest : IDisposable readonly ZipLatestObserver observer7; readonly ZipLatestObserver observer8; readonly ZipLatestObserver observer9; - - readonly object gate = new object(); + readonly Lock gate = new(); public _ZipLatest( Observer observer, @@ -1397,7 +1389,7 @@ public void TryPublishOnNext() { var result = resultSelector(observer1.GetValue(), observer2.GetValue(), observer3.GetValue(), observer4.GetValue(), observer5.GetValue(), observer6.GetValue(), observer7.GetValue(), observer8.GetValue(), observer9.GetValue()); observer.OnNext(result); - + if (observer1.IsCompleted || observer2.IsCompleted || observer3.IsCompleted || observer4.IsCompleted || observer5.IsCompleted || observer6.IsCompleted || observer7.IsCompleted || observer8.IsCompleted || observer9.IsCompleted) { observer.OnCompleted(); @@ -1519,8 +1511,7 @@ sealed class _ZipLatest : IDisposable readonly ZipLatestObserver observer8; readonly ZipLatestObserver observer9; readonly ZipLatestObserver observer10; - - readonly object gate = new object(); + readonly Lock gate = new(); public _ZipLatest( Observer observer, @@ -1589,7 +1580,7 @@ public void TryPublishOnNext() { var result = resultSelector(observer1.GetValue(), observer2.GetValue(), observer3.GetValue(), observer4.GetValue(), observer5.GetValue(), observer6.GetValue(), observer7.GetValue(), observer8.GetValue(), observer9.GetValue(), observer10.GetValue()); observer.OnNext(result); - + if (observer1.IsCompleted || observer2.IsCompleted || observer3.IsCompleted || observer4.IsCompleted || observer5.IsCompleted || observer6.IsCompleted || observer7.IsCompleted || observer8.IsCompleted || observer9.IsCompleted || observer10.IsCompleted) { observer.OnCompleted(); @@ -1715,8 +1706,7 @@ sealed class _ZipLatest : IDisposable readonly ZipLatestObserver observer9; readonly ZipLatestObserver observer10; readonly ZipLatestObserver observer11; - - readonly object gate = new object(); + readonly Lock gate = new(); public _ZipLatest( Observer observer, @@ -1789,7 +1779,7 @@ public void TryPublishOnNext() { var result = resultSelector(observer1.GetValue(), observer2.GetValue(), observer3.GetValue(), observer4.GetValue(), observer5.GetValue(), observer6.GetValue(), observer7.GetValue(), observer8.GetValue(), observer9.GetValue(), observer10.GetValue(), observer11.GetValue()); observer.OnNext(result); - + if (observer1.IsCompleted || observer2.IsCompleted || observer3.IsCompleted || observer4.IsCompleted || observer5.IsCompleted || observer6.IsCompleted || observer7.IsCompleted || observer8.IsCompleted || observer9.IsCompleted || observer10.IsCompleted || observer11.IsCompleted) { observer.OnCompleted(); @@ -1919,8 +1909,7 @@ sealed class _ZipLatest : IDisposable readonly ZipLatestObserver observer10; readonly ZipLatestObserver observer11; readonly ZipLatestObserver observer12; - - readonly object gate = new object(); + readonly Lock gate = new(); public _ZipLatest( Observer observer, @@ -1997,7 +1986,7 @@ public void TryPublishOnNext() { var result = resultSelector(observer1.GetValue(), observer2.GetValue(), observer3.GetValue(), observer4.GetValue(), observer5.GetValue(), observer6.GetValue(), observer7.GetValue(), observer8.GetValue(), observer9.GetValue(), observer10.GetValue(), observer11.GetValue(), observer12.GetValue()); observer.OnNext(result); - + if (observer1.IsCompleted || observer2.IsCompleted || observer3.IsCompleted || observer4.IsCompleted || observer5.IsCompleted || observer6.IsCompleted || observer7.IsCompleted || observer8.IsCompleted || observer9.IsCompleted || observer10.IsCompleted || observer11.IsCompleted || observer12.IsCompleted) { observer.OnCompleted(); @@ -2131,8 +2120,7 @@ sealed class _ZipLatest : IDisposable readonly ZipLatestObserver observer11; readonly ZipLatestObserver observer12; readonly ZipLatestObserver observer13; - - readonly object gate = new object(); + readonly Lock gate = new(); public _ZipLatest( Observer observer, @@ -2213,7 +2201,7 @@ public void TryPublishOnNext() { var result = resultSelector(observer1.GetValue(), observer2.GetValue(), observer3.GetValue(), observer4.GetValue(), observer5.GetValue(), observer6.GetValue(), observer7.GetValue(), observer8.GetValue(), observer9.GetValue(), observer10.GetValue(), observer11.GetValue(), observer12.GetValue(), observer13.GetValue()); observer.OnNext(result); - + if (observer1.IsCompleted || observer2.IsCompleted || observer3.IsCompleted || observer4.IsCompleted || observer5.IsCompleted || observer6.IsCompleted || observer7.IsCompleted || observer8.IsCompleted || observer9.IsCompleted || observer10.IsCompleted || observer11.IsCompleted || observer12.IsCompleted || observer13.IsCompleted) { observer.OnCompleted(); @@ -2351,8 +2339,7 @@ sealed class _ZipLatest : IDisposable readonly ZipLatestObserver observer12; readonly ZipLatestObserver observer13; readonly ZipLatestObserver observer14; - - readonly object gate = new object(); + readonly Lock gate = new(); public _ZipLatest( Observer observer, @@ -2437,7 +2424,7 @@ public void TryPublishOnNext() { var result = resultSelector(observer1.GetValue(), observer2.GetValue(), observer3.GetValue(), observer4.GetValue(), observer5.GetValue(), observer6.GetValue(), observer7.GetValue(), observer8.GetValue(), observer9.GetValue(), observer10.GetValue(), observer11.GetValue(), observer12.GetValue(), observer13.GetValue(), observer14.GetValue()); observer.OnNext(result); - + if (observer1.IsCompleted || observer2.IsCompleted || observer3.IsCompleted || observer4.IsCompleted || observer5.IsCompleted || observer6.IsCompleted || observer7.IsCompleted || observer8.IsCompleted || observer9.IsCompleted || observer10.IsCompleted || observer11.IsCompleted || observer12.IsCompleted || observer13.IsCompleted || observer14.IsCompleted) { observer.OnCompleted(); @@ -2579,8 +2566,7 @@ sealed class _ZipLatest : IDisposable readonly ZipLatestObserver observer13; readonly ZipLatestObserver observer14; readonly ZipLatestObserver observer15; - - readonly object gate = new object(); + readonly Lock gate = new(); public _ZipLatest( Observer observer, @@ -2669,7 +2655,7 @@ public void TryPublishOnNext() { var result = resultSelector(observer1.GetValue(), observer2.GetValue(), observer3.GetValue(), observer4.GetValue(), observer5.GetValue(), observer6.GetValue(), observer7.GetValue(), observer8.GetValue(), observer9.GetValue(), observer10.GetValue(), observer11.GetValue(), observer12.GetValue(), observer13.GetValue(), observer14.GetValue(), observer15.GetValue()); observer.OnNext(result); - + if (observer1.IsCompleted || observer2.IsCompleted || observer3.IsCompleted || observer4.IsCompleted || observer5.IsCompleted || observer6.IsCompleted || observer7.IsCompleted || observer8.IsCompleted || observer9.IsCompleted || observer10.IsCompleted || observer11.IsCompleted || observer12.IsCompleted || observer13.IsCompleted || observer14.IsCompleted || observer15.IsCompleted) { observer.OnCompleted(); diff --git a/src/R3/Operators/ZipLatest.tt b/src/R3/Operators/ZipLatest.tt index 023ceb70..b7050bfb 100644 --- a/src/R3/Operators/ZipLatest.tt +++ b/src/R3/Operators/ZipLatest.tt @@ -53,8 +53,8 @@ internal sealed class ZipLatest<<#= generateT(i) #>, TResult>( readonly Func<<#= generateT(i) #>, TResult> resultSelector; <# for (var j = 1; j <= i; j++ ) { #> readonly ZipLatestObserver> observer<#= j #>; -<# } #> - readonly object gate = new object(); +<# } #> + readonly Lock gate = new(); public _ZipLatest( Observer observer, @@ -95,7 +95,7 @@ internal sealed class ZipLatest<<#= generateT(i) #>, TResult>( { var result = resultSelector(<#= generateValue(i) #>); observer.OnNext(result); - + if (<#= generateIsCompletedOr(i) #>) { observer.OnCompleted(); diff --git a/src/R3/R3.csproj b/src/R3/R3.csproj index 96442227..504655b6 100644 --- a/src/R3/R3.csproj +++ b/src/R3/R3.csproj @@ -4,7 +4,7 @@ netstandard2.0;netstandard2.1;net6.0;net8.0 enable enable - 12 + 13 true true diff --git a/src/R3/TimerFrameProvider.cs b/src/R3/TimerFrameProvider.cs index 0eb8fc68..d44a67ed 100644 --- a/src/R3/TimerFrameProvider.cs +++ b/src/R3/TimerFrameProvider.cs @@ -4,7 +4,7 @@ public sealed class TimerFrameProvider : FrameProvider, IDisposable { static readonly TimerCallback timerCallback = Run; - readonly object gate = new object(); + readonly Lock gate = new(); long frameCount; bool disposed; FreeListCore list;