From 43ae081031d352e05d50a0e9730070d55d075bba Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 6 Mar 2023 16:24:27 +0700 Subject: Refactor singleton initialization --- crypto/src/asn1/DerObjectIdentifier.cs | 2 +- crypto/src/util/Objects.cs | 18 +++++++++++++++++- crypto/src/x509/X509Certificate.cs | 23 ++++++++++------------- crypto/src/x509/X509Crl.cs | 17 ++++++++--------- 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(ref TValue value, TArg arg, + Func 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); } /// @@ -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); } } } -- cgit 1.4.1