diff --git a/src/StackExchange.Redis/ConnectionMultiplexer.Debug.cs b/src/StackExchange.Redis/ConnectionMultiplexer.Debug.cs index da3f61be9..9b30ac141 100644 --- a/src/StackExchange.Redis/ConnectionMultiplexer.Debug.cs +++ b/src/StackExchange.Redis/ConnectionMultiplexer.Debug.cs @@ -5,7 +5,7 @@ namespace StackExchange.Redis; public partial class ConnectionMultiplexer { private static int _collectedWithoutDispose; - internal static int CollectedWithoutDispose => Thread.VolatileRead(ref _collectedWithoutDispose); + internal static int CollectedWithoutDispose => Volatile.Read(ref _collectedWithoutDispose); /// /// Invoked by the garbage collector. diff --git a/src/StackExchange.Redis/ConnectionMultiplexer.cs b/src/StackExchange.Redis/ConnectionMultiplexer.cs index 4b06baf27..cc766338a 100644 --- a/src/StackExchange.Redis/ConnectionMultiplexer.cs +++ b/src/StackExchange.Redis/ConnectionMultiplexer.cs @@ -58,17 +58,17 @@ public sealed partial class ConnectionMultiplexer : IInternalConnectionMultiplex private int lastReconfigiureTicks = Environment.TickCount; internal long LastReconfigureSecondsAgo => - unchecked(Environment.TickCount - Thread.VolatileRead(ref lastReconfigiureTicks)) / 1000; + unchecked(Environment.TickCount - Volatile.Read(ref lastReconfigiureTicks)) / 1000; private int _activeHeartbeatErrors, lastHeartbeatTicks; internal long LastHeartbeatSecondsAgo => pulse is null ? -1 - : unchecked(Environment.TickCount - Thread.VolatileRead(ref lastHeartbeatTicks)) / 1000; + : unchecked(Environment.TickCount - Volatile.Read(ref lastHeartbeatTicks)) / 1000; private static int lastGlobalHeartbeatTicks = Environment.TickCount; internal static long LastGlobalHeartbeatSecondsAgo => - unchecked(Environment.TickCount - Thread.VolatileRead(ref lastGlobalHeartbeatTicks)) / 1000; + unchecked(Environment.TickCount - Volatile.Read(ref lastGlobalHeartbeatTicks)) / 1000; /// [Obsolete($"Please use {nameof(ConfigurationOptions)}.{nameof(ConfigurationOptions.IncludeDetailInExceptions)} instead - this will be removed in 3.0.")] diff --git a/src/StackExchange.Redis/PhysicalBridge.cs b/src/StackExchange.Redis/PhysicalBridge.cs index c430cf5af..1a38b7d89 100644 --- a/src/StackExchange.Redis/PhysicalBridge.cs +++ b/src/StackExchange.Redis/PhysicalBridge.cs @@ -555,7 +555,7 @@ internal void OnFullyEstablished(PhysicalConnection connection, string source) private bool DueForConnectRetry() { - int connectTimeMilliseconds = unchecked(Environment.TickCount - Thread.VolatileRead(ref connectStartTicks)); + int connectTimeMilliseconds = unchecked(Environment.TickCount - Volatile.Read(ref connectStartTicks)); return Multiplexer.RawConfig.ReconnectRetryPolicy.ShouldRetry(Interlocked.Read(ref connectTimeoutRetryCount), connectTimeMilliseconds); } diff --git a/src/StackExchange.Redis/PhysicalConnection.cs b/src/StackExchange.Redis/PhysicalConnection.cs index 129fd9e07..c21bc07fc 100644 --- a/src/StackExchange.Redis/PhysicalConnection.cs +++ b/src/StackExchange.Redis/PhysicalConnection.cs @@ -261,8 +261,8 @@ private enum ReadMode : byte private readonly WeakReference _bridge; public PhysicalBridge? BridgeCouldBeNull => (PhysicalBridge?)_bridge.Target; - public long LastReadSecondsAgo => unchecked(Environment.TickCount - Thread.VolatileRead(ref lastReadTickCount)) / 1000; - public long LastWriteSecondsAgo => unchecked(Environment.TickCount - Thread.VolatileRead(ref lastWriteTickCount)) / 1000; + public long LastReadSecondsAgo => unchecked(Environment.TickCount - Volatile.Read(ref lastReadTickCount)) / 1000; + public long LastWriteSecondsAgo => unchecked(Environment.TickCount - Volatile.Read(ref lastWriteTickCount)) / 1000; private bool IncludeDetailInExceptions => BridgeCouldBeNull?.Multiplexer.RawConfig.IncludeDetailInExceptions ?? false; @@ -418,8 +418,8 @@ public void RecordConnectionFailed( if (isCurrent && Interlocked.CompareExchange(ref failureReported, 1, 0) == 0) { - int now = Environment.TickCount, lastRead = Thread.VolatileRead(ref lastReadTickCount), lastWrite = Thread.VolatileRead(ref lastWriteTickCount), - lastBeat = Thread.VolatileRead(ref lastBeatTickCount); + int now = Environment.TickCount, lastRead = Volatile.Read(ref lastReadTickCount), lastWrite = Volatile.Read(ref lastWriteTickCount), + lastBeat = Volatile.Read(ref lastBeatTickCount); int unansweredWriteTime = 0; lock (_writtenAwaitingResponse) @@ -434,7 +434,7 @@ public void RecordConnectionFailed( var exMessage = new StringBuilder(failureType.ToString()); // If the reason for the shutdown was we asked for the socket to die, don't log it as an error (only informational) - weAskedForThis = Thread.VolatileRead(ref clientSentQuit) != 0; + weAskedForThis = Volatile.Read(ref clientSentQuit) != 0; var pipe = connectingPipe ?? _ioPipe; if (pipe is SocketConnection sc) diff --git a/src/StackExchange.Redis/Profiling/ProfilingSession.cs b/src/StackExchange.Redis/Profiling/ProfilingSession.cs index f83a49c91..3bc3caf38 100644 --- a/src/StackExchange.Redis/Profiling/ProfilingSession.cs +++ b/src/StackExchange.Redis/Profiling/ProfilingSession.cs @@ -24,7 +24,7 @@ internal void Add(ProfiledCommand command) { if (command == null) return; - object? cur = Thread.VolatileRead(ref _untypedHead); + object? cur = Volatile.Read(ref _untypedHead); while (true) { command.NextElement = (ProfiledCommand?)cur; diff --git a/src/StackExchange.Redis/ServerEndPoint.cs b/src/StackExchange.Redis/ServerEndPoint.cs index af98af0f7..f856a5b21 100644 --- a/src/StackExchange.Redis/ServerEndPoint.cs +++ b/src/StackExchange.Redis/ServerEndPoint.cs @@ -719,7 +719,7 @@ internal void OnFullyEstablished(PhysicalConnection connection, string source) } internal int LastInfoReplicationCheckSecondsAgo => - unchecked(Environment.TickCount - Thread.VolatileRead(ref lastInfoReplicationCheckTicks)) / 1000; + unchecked(Environment.TickCount - Volatile.Read(ref lastInfoReplicationCheckTicks)) / 1000; private EndPoint? primaryEndPoint; public EndPoint? PrimaryEndPoint diff --git a/tests/StackExchange.Redis.Tests/FailoverTests.cs b/tests/StackExchange.Redis.Tests/FailoverTests.cs index 68f8f2266..1f33275b5 100644 --- a/tests/StackExchange.Redis.Tests/FailoverTests.cs +++ b/tests/StackExchange.Redis.Tests/FailoverTests.cs @@ -217,7 +217,7 @@ public async Task SubscriptionsSurviveConnectionFailureAsync() await sub.PingAsync(); await Task.Delay(200).ConfigureAwait(false); - var counter1 = Thread.VolatileRead(ref counter); + var counter1 = Volatile.Read(ref counter); Log($"Expecting 1 message, got {counter1}"); Assert.Equal(1, counter1); @@ -274,9 +274,9 @@ public async Task SubscriptionsSurviveConnectionFailureAsync() // Give it a few seconds to get our messages Log("Waiting for 2 messages"); - await UntilConditionAsync(TimeSpan.FromSeconds(5), () => Thread.VolatileRead(ref counter) == 2); + await UntilConditionAsync(TimeSpan.FromSeconds(5), () => Volatile.Read(ref counter) == 2); - var counter2 = Thread.VolatileRead(ref counter); + var counter2 = Volatile.Read(ref counter); Log($"Expecting 2 messages, got {counter2}"); Assert.Equal(2, counter2); diff --git a/tests/StackExchange.Redis.Tests/PubSubTests.cs b/tests/StackExchange.Redis.Tests/PubSubTests.cs index 9418fe80f..a3dadb07e 100644 --- a/tests/StackExchange.Redis.Tests/PubSubTests.cs +++ b/tests/StackExchange.Redis.Tests/PubSubTests.cs @@ -30,19 +30,19 @@ public async Task ExplicitPublishMode() #pragma warning restore CS0618 await UntilConditionAsync( TimeSpan.FromSeconds(10), - () => Thread.VolatileRead(ref b) == 1 - && Thread.VolatileRead(ref c) == 1 - && Thread.VolatileRead(ref d) == 1); - Assert.Equal(0, Thread.VolatileRead(ref a)); - Assert.Equal(1, Thread.VolatileRead(ref b)); - Assert.Equal(1, Thread.VolatileRead(ref c)); - Assert.Equal(1, Thread.VolatileRead(ref d)); + () => Volatile.Read(ref b) == 1 + && Volatile.Read(ref c) == 1 + && Volatile.Read(ref d) == 1); + Assert.Equal(0, Volatile.Read(ref a)); + Assert.Equal(1, Volatile.Read(ref b)); + Assert.Equal(1, Volatile.Read(ref c)); + Assert.Equal(1, Volatile.Read(ref d)); #pragma warning disable CS0618 pub.Publish("*bcd", "efg"); #pragma warning restore CS0618 - await UntilConditionAsync(TimeSpan.FromSeconds(10), () => Thread.VolatileRead(ref a) == 1); - Assert.Equal(1, Thread.VolatileRead(ref a)); + await UntilConditionAsync(TimeSpan.FromSeconds(10), () => Volatile.Read(ref a) == 1); + Assert.Equal(1, Volatile.Read(ref a)); } [Theory] @@ -86,7 +86,7 @@ public async Task TestBasicPubSub(string? channelPrefix, bool wildCard, string b { Assert.Empty(received); } - Assert.Equal(0, Thread.VolatileRead(ref secondHandler)); + Assert.Equal(0, Volatile.Read(ref secondHandler)); #pragma warning disable CS0618 var count = sub.Publish(pubChannel, "def"); #pragma warning restore CS0618 @@ -99,8 +99,8 @@ public async Task TestBasicPubSub(string? channelPrefix, bool wildCard, string b Assert.Single(received); } // Give handler firing a moment - await UntilConditionAsync(TimeSpan.FromSeconds(2), () => Thread.VolatileRead(ref secondHandler) == 1); - Assert.Equal(1, Thread.VolatileRead(ref secondHandler)); + await UntilConditionAsync(TimeSpan.FromSeconds(2), () => Volatile.Read(ref secondHandler) == 1); + Assert.Equal(1, Volatile.Read(ref secondHandler)); // unsubscribe from first; should still see second #pragma warning disable CS0618 @@ -113,9 +113,9 @@ public async Task TestBasicPubSub(string? channelPrefix, bool wildCard, string b Assert.Single(received); } - await UntilConditionAsync(TimeSpan.FromSeconds(2), () => Thread.VolatileRead(ref secondHandler) == 2); + await UntilConditionAsync(TimeSpan.FromSeconds(2), () => Volatile.Read(ref secondHandler) == 2); - var secondHandlerCount = Thread.VolatileRead(ref secondHandler); + var secondHandlerCount = Volatile.Read(ref secondHandler); Log("Expecting 2 from second handler, got: " + secondHandlerCount); Assert.Equal(2, secondHandlerCount); Assert.Equal(1, count); @@ -130,7 +130,7 @@ public async Task TestBasicPubSub(string? channelPrefix, bool wildCard, string b { Assert.Single(received); } - secondHandlerCount = Thread.VolatileRead(ref secondHandler); + secondHandlerCount = Volatile.Read(ref secondHandler); Log("Expecting 2 from second handler, got: " + secondHandlerCount); Assert.Equal(2, secondHandlerCount); Assert.Equal(0, count); @@ -170,7 +170,7 @@ public async Task TestBasicPubSubFireAndForget() { Assert.Empty(received); } - Assert.Equal(0, Thread.VolatileRead(ref secondHandler)); + Assert.Equal(0, Volatile.Read(ref secondHandler)); await PingAsync(pub, sub).ForAwait(); var count = sub.Publish(key, "def", CommandFlags.FireAndForget); await PingAsync(pub, sub).ForAwait(); @@ -182,7 +182,7 @@ public async Task TestBasicPubSubFireAndForget() { Assert.Single(received); } - Assert.Equal(1, Thread.VolatileRead(ref secondHandler)); + Assert.Equal(1, Volatile.Read(ref secondHandler)); sub.Unsubscribe(key); count = sub.Publish(key, "ghi", CommandFlags.FireAndForget); @@ -241,7 +241,7 @@ public async Task TestPatternPubSub() { Assert.Empty(received); } - Assert.Equal(0, Thread.VolatileRead(ref secondHandler)); + Assert.Equal(0, Volatile.Read(ref secondHandler)); await PingAsync(pub, sub).ForAwait(); var count = sub.Publish(RedisChannel.Literal("abc"), "def"); @@ -254,8 +254,8 @@ public async Task TestPatternPubSub() } // Give reception a bit, the handler could be delayed under load - await UntilConditionAsync(TimeSpan.FromSeconds(2), () => Thread.VolatileRead(ref secondHandler) == 1); - Assert.Equal(1, Thread.VolatileRead(ref secondHandler)); + await UntilConditionAsync(TimeSpan.FromSeconds(2), () => Volatile.Read(ref secondHandler) == 1); + Assert.Equal(1, Volatile.Read(ref secondHandler)); #pragma warning disable CS0618 sub.Unsubscribe("a*c"); diff --git a/tests/StackExchange.Redis.Tests/SyncContextTests.cs b/tests/StackExchange.Redis.Tests/SyncContextTests.cs index 8eddc9f1d..b98caefeb 100644 --- a/tests/StackExchange.Redis.Tests/SyncContextTests.cs +++ b/tests/StackExchange.Redis.Tests/SyncContextTests.cs @@ -118,7 +118,7 @@ public MySyncContext(TextWriter log) _log = log; SetSynchronizationContext(this); } - public int OpCount => Thread.VolatileRead(ref _opCount); + public int OpCount => Volatile.Read(ref _opCount); private int _opCount; private void Incr() => Interlocked.Increment(ref _opCount);