Improve DerObjectIdentifier cache
- see https://github.com/bcgit/bc-csharp/pull/416
1 files 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)
|