From d03b1ce65d4077e2895acfce3bc286ea501669aa Mon Sep 17 00:00:00 2001 From: Christopher Watford <83599748+watfordsuzy@users.noreply.github.com> Date: Mon, 15 Apr 2024 08:55:57 -0400 Subject: [PATCH] fix: do not recreate Random each time (#945) * fix: do not recreate Random each time On .NET Framework it is incorrect to recreate Random instances each time, these should instead be one per instance. On .NET Core and later this is not a limitation, but the libraries share a codebase. Fixes #944 * Use a thread safe Random instance #944 * Forgot to commit csproj change #944 * Address PR comment #944 --- Box.V2/Box.V2.csproj | 3 ++- Box.V2/Utility/ExponentialBackoff.cs | 5 +++-- Box.V2/Utility/ThreadSafeRandom.cs | 31 ++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 Box.V2/Utility/ThreadSafeRandom.cs diff --git a/Box.V2/Box.V2.csproj b/Box.V2/Box.V2.csproj index 8cfd492d3..380a2a750 100644 --- a/Box.V2/Box.V2.csproj +++ b/Box.V2/Box.V2.csproj @@ -276,6 +276,7 @@ + @@ -343,4 +344,4 @@ - \ No newline at end of file + diff --git a/Box.V2/Utility/ExponentialBackoff.cs b/Box.V2/Utility/ExponentialBackoff.cs index aa06edbe7..55f29d569 100644 --- a/Box.V2/Utility/ExponentialBackoff.cs +++ b/Box.V2/Utility/ExponentialBackoff.cs @@ -10,9 +10,10 @@ public TimeSpan GetRetryTimeout(int numRetries) const double RETRY_RANDOMIZATION_FACTOR = 0.5; var minRandomization = 1 - RETRY_RANDOMIZATION_FACTOR; var maxRandomization = 1 + RETRY_RANDOMIZATION_FACTOR; - var random = new Random(); - var randomization = random.NextDouble() * (maxRandomization - minRandomization) + minRandomization; + var randomization = ThreadSafeRandom.Instance.NextDouble() + * (maxRandomization - minRandomization) + minRandomization; + var exponential = Math.Pow(2, numRetries - 1); var result = Math.Ceiling(exponential * baseInterval.TotalSeconds * randomization); return TimeSpan.FromSeconds(result); diff --git a/Box.V2/Utility/ThreadSafeRandom.cs b/Box.V2/Utility/ThreadSafeRandom.cs new file mode 100644 index 000000000..76ac32324 --- /dev/null +++ b/Box.V2/Utility/ThreadSafeRandom.cs @@ -0,0 +1,31 @@ +using System; +using System.Runtime.CompilerServices; + +namespace Box.V2.Utility +{ + /// + /// A thread safe implementation of , following best practices + /// for .NET Framework and .NET Standard. + /// + /// + internal static class ThreadSafeRandom + { + // + // Adapted from https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Random.cs + // + // NOTE: when/if this library updates to .NET 6+, this code can be replaced with `Random.Shared` + // + + [ThreadStatic] + private static Random _random; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static Random CreateRandom() => _random = new Random(); + + /// + /// An instance of specific to the calling thread. + /// Do not pass this instance to other threads or contexts. + /// + public static Random Instance => _random ?? CreateRandom(); + } +}