summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crypto/src/asn1/DerObjectIdentifier.cs2
-rw-r--r--crypto/src/util/Objects.cs18
-rw-r--r--crypto/src/x509/X509Certificate.cs23
-rw-r--r--crypto/src/x509/X509Crl.cs17
4 files changed, 36 insertions, 24 deletions
diff --git a/crypto/src/asn1/DerObjectIdentifier.cs b/crypto/src/asn1/DerObjectIdentifier.cs
index 96e61cdc5..44388d51f 100644
--- a/crypto/src/asn1/DerObjectIdentifier.cs
+++ b/crypto/src/asn1/DerObjectIdentifier.cs
@@ -212,7 +212,7 @@ namespace Org.BouncyCastle.Asn1
             index ^= index >> 10;
             index &= 1023;
 
-            var originalEntry = Cache[index];
+            var originalEntry = Volatile.Read(ref Cache[index]);
             if (originalEntry != null && Arrays.AreEqual(contents, originalEntry.GetContents()))
                 return originalEntry;
 
diff --git a/crypto/src/util/Objects.cs b/crypto/src/util/Objects.cs
index 4d49ac9de..e1ef8c117 100644
--- a/crypto/src/util/Objects.cs
+++ b/crypto/src/util/Objects.cs
@@ -1,4 +1,7 @@
-namespace Org.BouncyCastle.Utilities
+using System;
+using System.Threading;
+
+namespace Org.BouncyCastle.Utilities
 {
     public static class Objects
     {
@@ -6,5 +9,18 @@
         {
             return null == obj ? 0 : obj.GetHashCode();
         }
+
+        internal static TValue EnsureSingletonInitialized<TValue, TArg>(ref TValue value, TArg arg,
+            Func<TArg, TValue> initialize)
+            where TValue : class
+        {
+            TValue currentValue = Volatile.Read(ref value);
+            if (null != currentValue)
+                return currentValue;
+
+            TValue candidateValue = initialize(arg);
+
+            return Interlocked.CompareExchange(ref value, candidateValue, null) ?? candidateValue;
+        }
     }
 }
diff --git a/crypto/src/x509/X509Certificate.cs b/crypto/src/x509/X509Certificate.cs
index f58477439..cd3d6d680 100644
--- a/crypto/src/x509/X509Certificate.cs
+++ b/crypto/src/x509/X509Certificate.cs
@@ -3,7 +3,6 @@ using System.Collections.Generic;
 using System.IO;
 using System.Net;
 using System.Text;
-using System.Threading;
 
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.Misc;
@@ -471,13 +470,7 @@ namespace Org.BouncyCastle.X509
         public virtual AsymmetricKeyParameter GetPublicKey()
         {
             // Cache the public key to support repeated-use optimizations
-            AsymmetricKeyParameter localPublicKeyValue = publicKeyValue;
-            if (null != localPublicKeyValue)
-                return localPublicKeyValue;
-
-            AsymmetricKeyParameter temp = PublicKeyFactory.CreateKey(c.SubjectPublicKeyInfo);
-
-            return Interlocked.CompareExchange(ref publicKeyValue, temp, null) ?? temp;
+            return Objects.EnsureSingletonInitialized(ref publicKeyValue, c, CreatePublicKey);
         }
 
         /// <summary>
@@ -681,10 +674,11 @@ namespace Org.BouncyCastle.X509
 
         private CachedEncoding GetCachedEncoding()
         {
-            CachedEncoding localCachedEncoding = cachedEncoding;
-            if (null != localCachedEncoding)
-                return localCachedEncoding;
+            return Objects.EnsureSingletonInitialized(ref cachedEncoding, c, CreateCachedEncoding);
+        }
 
+        private static CachedEncoding CreateCachedEncoding(X509CertificateStructure c)
+        {
             byte[] encoding = null;
             CertificateEncodingException exception = null;
             try
@@ -696,9 +690,12 @@ namespace Org.BouncyCastle.X509
                 exception = new CertificateEncodingException("Failed to DER-encode certificate", e);
             }
 
-            CachedEncoding temp = new CachedEncoding(encoding, exception);
+            return new CachedEncoding(encoding, exception);
+        }
 
-           return Interlocked.CompareExchange(ref cachedEncoding, temp, null) ?? temp;
+        private static AsymmetricKeyParameter CreatePublicKey(X509CertificateStructure c)
+        {
+            return PublicKeyFactory.CreateKey(c.SubjectPublicKeyInfo);
         }
 
         private static bool IsAlgIDEqual(AlgorithmIdentifier id1, AlgorithmIdentifier id2)
diff --git a/crypto/src/x509/X509Crl.cs b/crypto/src/x509/X509Crl.cs
index b4af1b374..81dd1c20e 100644
--- a/crypto/src/x509/X509Crl.cs
+++ b/crypto/src/x509/X509Crl.cs
@@ -2,7 +2,7 @@ using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Text;
-using System.Threading;
+
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.Utilities;
 using Org.BouncyCastle.Asn1.X509;
@@ -17,7 +17,7 @@ using Org.BouncyCastle.X509.Extension;
 
 namespace Org.BouncyCastle.X509
 {
-	/**
+    /**
 	 * The following extensions are listed in RFC 2459 as relevant to CRLs
 	 *
 	 * Authority Key Identifier
@@ -26,7 +26,7 @@ namespace Org.BouncyCastle.X509
 	 * Delta CRL Indicator (critical)
 	 * Issuing Distribution Point (critical)
 	 */
-	public class X509Crl
+    public class X509Crl
 		: X509ExtensionBase
 		// TODO Add interface Crl?
 	{
@@ -449,10 +449,11 @@ namespace Org.BouncyCastle.X509
 
         private CachedEncoding GetCachedEncoding()
         {
-			CachedEncoding localCacheEncoding = cachedEncoding;
-            if (null != localCacheEncoding)
-                return localCacheEncoding;
+			return Objects.EnsureSingletonInitialized(ref cachedEncoding, c, CreateCachedEncoding);
+        }
 
+		private static CachedEncoding CreateCachedEncoding(CertificateList c)
+		{
             byte[] encoding = null;
             CrlException exception = null;
             try
@@ -464,9 +465,7 @@ namespace Org.BouncyCastle.X509
                 exception = new CrlException("Failed to DER-encode CRL", e);
             }
 
-            CachedEncoding temp = new CachedEncoding(encoding, exception);
-
-			return Interlocked.CompareExchange(ref cachedEncoding, temp, null) ?? temp;
+            return new CachedEncoding(encoding, exception);
         }
     }
 }