From b0ac018a1ae1c7ab19ba047d50b9b4353ba2e0a7 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Tue, 14 Feb 2023 14:31:49 +0700 Subject: Improve DerObjectIdentifier cache - see https://github.com/bcgit/bc-csharp/pull/416 --- crypto/src/asn1/DerObjectIdentifier.cs | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/crypto/src/asn1/DerObjectIdentifier.cs b/crypto/src/asn1/DerObjectIdentifier.cs index 06a7b25f3..96e61cdc5 100644 --- a/crypto/src/asn1/DerObjectIdentifier.cs +++ b/crypto/src/asn1/DerObjectIdentifier.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Text; +using System.Threading; using Org.BouncyCastle.Math; using Org.BouncyCastle.Utilities; @@ -205,19 +206,26 @@ namespace Org.BouncyCastle.Asn1 internal static DerObjectIdentifier CreatePrimitive(byte[] contents, bool clone) { - int hashCode = Arrays.GetHashCode(contents); - int first = hashCode & 1023; + int index = Arrays.GetHashCode(contents); - lock (Cache) - { - DerObjectIdentifier entry = Cache[first]; - if (entry != null && Arrays.AreEqual(contents, entry.GetContents())) - { - return entry; - } + index ^= index >> 20; + index ^= index >> 10; + index &= 1023; + + var originalEntry = Cache[index]; + if (originalEntry != null && Arrays.AreEqual(contents, originalEntry.GetContents())) + return originalEntry; - return Cache[first] = new DerObjectIdentifier(contents, clone); + var newEntry = new DerObjectIdentifier(contents, clone); + + var exchangedEntry = Interlocked.CompareExchange(ref Cache[index], newEntry, originalEntry); + if (exchangedEntry != originalEntry) + { + if (exchangedEntry != null && Arrays.AreEqual(contents, exchangedEntry.GetContents())) + return exchangedEntry; } + + return newEntry; } private static bool IsValidIdentifier(string identifier) -- cgit 1.4.1