diff --git a/TheSquid.Numerics.Extensions/PowCachedExtension.cs b/TheSquid.Numerics.Extensions/PowCachedExtension.cs index abc447d..9ac9636 100644 --- a/TheSquid.Numerics.Extensions/PowCachedExtension.cs +++ b/TheSquid.Numerics.Extensions/PowCachedExtension.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; +using System.Runtime.CompilerServices; namespace TheSquid.Numerics { @@ -16,11 +17,6 @@ public static partial class PowCachedExtension /// private static Dictionary, ValueTuple> powCache; - /// - /// Cache access synchronization object. - /// - private static Object syncObject; - /// /// Life time counter for sort items by age. /// @@ -37,7 +33,6 @@ public static partial class PowCachedExtension static PowCachedExtension() { powCache = new Dictionary, ValueTuple>(); - syncObject = new Object(); itemsLifetime = 0; } @@ -70,28 +65,27 @@ public static BigInteger Pow(this ref BigInteger basement, int exponent) /// /// The result of raising basement to the exponent power. /// + [MethodImpl(MethodImplOptions.Synchronized)] public static BigInteger PowCached(this ref BigInteger basement, int exponent) { - lock (syncObject) + try { - try - { - const string negativeExponentMessage = "Negative exponent values are not supported."; - if (exponent < 0) throw new ArgumentOutOfRangeException(negativeExponentMessage); - if (itemsLifetime >= int.MaxValue) ShrinkCacheData(powCache.LongCount() / 2); - return CalculateNewValue(ref basement, exponent); - } - catch (OutOfMemoryException) - { - if (powCache.LongCount() > 0) ShrinkCacheData(0); - return CalculateNewValue(ref basement, exponent); - } + const string negativeExponentMessage = "Negative exponent values are not supported."; + if (exponent < 0) throw new ArgumentOutOfRangeException(negativeExponentMessage); + if (itemsLifetime >= int.MaxValue) ShrinkCacheData(powCache.LongCount() / 2); + return CalculateNewValue(ref basement, exponent); + } + catch (OutOfMemoryException) + { + if (powCache.LongCount() > 0) ShrinkCacheData(0); + return CalculateNewValue(ref basement, exponent); } } /// /// Get power result from cache. /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool TryGetValue(ref BigInteger basement, int exponent, out BigInteger power) { var key = new ValueTuple(basement, exponent); @@ -104,6 +98,7 @@ private static bool TryGetValue(ref BigInteger basement, int exponent, out BigIn /// /// Put power result to cache. /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void CacheNewValue(ref BigInteger basement, int exponent, BigInteger power) { var key = new ValueTuple(basement, exponent); @@ -114,6 +109,7 @@ private static void CacheNewValue(ref BigInteger basement, int exponent, BigInte /// /// Calculate new power value. /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static BigInteger CalculateNewValue(ref BigInteger basement, int exponent) { if (exponent == 0) return 1; @@ -138,26 +134,24 @@ private static BigInteger CalculateNewValue(ref BigInteger basement, int exponen /// /// Associated items count value in the ItemsCount property. /// + [MethodImpl(MethodImplOptions.Synchronized)] public static void ShrinkCacheData(long itemsInCache) { - lock (syncObject) + if (itemsInCache == 0) + { + if (powCache.LongCount() == 0) return; + itemsLifetime = 0; + powCache.Clear(); + GC.Collect(); + GC.WaitForPendingFinalizers(); + } + else { - if (itemsInCache == 0) - { - if (powCache.LongCount() == 0) return; - itemsLifetime = 0; - powCache.Clear(); - GC.Collect(); - GC.WaitForPendingFinalizers(); - } - else - { - itemsLifetime = 0; - powCache = powCache - .OrderBy(p => p.Value.Item2) - .Skip((int)Math.Min(powCache.LongCount() - itemsInCache, int.MaxValue)) - .ToDictionary(p => p.Key, p => new ValueTuple(p.Value.Item1, ++itemsLifetime)); - } + itemsLifetime = 0; + powCache = powCache + .OrderBy(p => p.Value.Item2) + .Skip((int)Math.Min(powCache.LongCount() - itemsInCache, int.MaxValue)) + .ToDictionary(p => p.Key, p => new ValueTuple(p.Value.Item1, ++itemsLifetime)); } } }