LazyInitializer.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Threading / LazyInitializer.cs / 1305376 / LazyInitializer.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// 
// LazyInitializer.cs 
//
// [....] 
//
// a set of lightweight static helpers for lazy initialization.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 

 
using System.Security.Permissions; 
using System.Diagnostics.Contracts;
namespace System.Threading 
{

    /// 
    /// Specifies how a  instance should synchronize access among multiple threads. 
    /// 
    public enum LazyThreadSafetyMode 
    { 
        /// 
        /// This mode makes no guarantees around the thread-safety of the  instance.  If used from multiple threads, the behavior of the  is undefined. 
        /// This mode should be used when a  is guaranteed to never be initialized from more than one thread simultaneously and high performance is crucial.
        /// If valueFactory throws an exception when the  is initialized, the exception will be cached and returned on subsequent accesses to Value. Also, if valueFactory recursively
        /// accesses Value on this  instance, a  will be thrown.
        ///  
        None,
 
        ///  
        /// When multiple threads attempt to simultaneously initialize a  instance, this mode allows each thread to execute the
        /// valueFactory but only the first thread to complete initialization will be allowed to set the final value of the  . 
        /// Once initialized successfully, any future calls to Value will return the cached result.  If valueFactory throws an exception on any thread, that exception will be
        /// propagated out of Value. If any thread executes valueFactory without throwing an exception and, therefore, successfully sets the value, that value will be returned on
        /// subsequent accesses to Value from any thread.  If no thread succeeds in setting the value, IsValueCreated will remain false and subsequent accesses to Value will result in
        /// the valueFactory delegate re-executing.  Also, if valueFactory recursively accesses Value on this   instance, an exception will NOT be thrown. 
        /// 
        PublicationOnly, 
 
        /// 
        /// This mode uses locks to ensure that only a single thread can initialize a  instance in a thread-safe manner.  In general, 
        /// taken if this mode is used in conjunction with a  valueFactory delegate that uses locks internally, a deadlock can occur if not
        /// handled carefully.  If valueFactory throws an exception when the is initialized, the exception will be cached and returned on
        /// subsequent accesses to Value. Also, if valueFactory recursively accesses Value on this  instance, a   will be thrown.
        ///  
        ExecutionAndPublication
    } 
    ///  
    /// Provides lazy initialization routines.
    ///  
    /// 
    /// These routines avoid needing to allocate a dedicated, lazy-initialization instance, instead using
    /// references to ensure targets have been initialized as they are accessed.
    ///  
    [HostProtection(Synchronization = true, ExternalThreading = true)]
    public static class LazyInitializer 
    { 
        // The following field is used wherever we need to insert a volatile read.
        private static volatile object s_barrier = null; 

        /// 
        /// Initializes a target reference type with the type's default constructor if the target has not
        /// already been initialized. 
        /// 
        /// The refence type of the reference to be initialized. 
        /// A reference of type  to initialize if it has not 
        /// already been initialized.
        /// The initialized reference of type . 
        /// Type  does not have a default
        /// constructor.
        /// 
        /// Permissions to access the constructor of type  were missing. 
        /// 
        ///  
        ///  
        /// This method may only be used on reference types. To ensure initialization of value
        /// types, see other overloads of EnsureInitialized. 
        /// 
        /// 
        /// This method may be used concurrently by multiple threads to initialize .
        /// In the event that multiple threads access this method concurrently, multiple instances of  
        /// may be created, but only one will be stored into . In such an occurrence, this method will not dispose of the
        /// objects that were not stored.  If such objects must be disposed, it is up to the caller to determine 
        /// if an object was not used and to then dispose of the object appropriately. 
        /// 
        ///  
        public static T EnsureInitialized(ref T target) where T : class
        {
            // Fast path.
            if (target != null) 
            {
                object barrierGarbage = s_barrier; // Insert a volatile load barrier. Needed on IA64. 
                return target; 
            }
 
            return EnsureInitializedCore(ref target, LazyHelpers.s_activatorFactorySelector);
        }

        ///  
        /// Initializes a target reference type using the specified function if it has not already been
        /// initialized. 
        ///  
        /// The reference type of the reference to be initialized.
        /// The reference of type  to initialize if it has not 
        /// already been initialized.
        /// The  invoked to initialize the
        /// reference.
        /// The initialized reference of type . 
        /// Type  does not have a
        /// default constructor. 
        ///  returned 
        /// null.
        ///  
        /// 
        /// This method may only be used on reference types, and  may
        /// not return a null reference (Nothing in Visual Basic). To ensure initialization of value types or
        /// to allow null reference types, see other overloads of EnsureInitialized. 
        /// 
        ///  
        /// This method may be used concurrently by multiple threads to initialize . 
        /// In the event that multiple threads access this method concurrently, multiple instances of 
        /// may be created, but only one will be stored into . In such an occurrence, this method will not dispose of the 
        /// objects that were not stored.  If such objects must be disposed, it is up to the caller to determine
        /// if an object was not used and to then dispose of the object appropriately.
        /// 
        ///  
        public static T EnsureInitialized(ref T target, Func valueFactory) where T : class
        { 
            // Fast path. 
            if (target != null)
            { 
                object barrierGarbage = s_barrier; // Insert a volatile load barrier. Needed on IA64.
                return target;
            }
 
            return EnsureInitializedCore(ref target, valueFactory);
        } 
 
        /// 
        /// Initialize the target using the given delegate (slow path). 
        /// 
        /// The reference type of the reference to be initialized.
        /// The variable that need to be initialized
        /// The delegate that will be executed to initialize the target 
        /// The initialized variable
        private static T EnsureInitializedCore(ref T target, Func valueFactory) where T : class 
        { 
            T value = valueFactory();
            if (value == null) 
            {
                throw new InvalidOperationException(Environment.GetResourceString("Lazy_StaticInit_InvalidOperation"));
            }
 
            Interlocked.CompareExchange(ref target, value, null);
            Contract.Assert(target != null); 
            return target; 
        }
 

        /// 
        /// Initializes a target reference or value type with its default constructor if it has not already
        /// been initialized. 
        /// 
        /// The type of the reference to be initialized. 
        /// A reference or value of type  to initialize if it 
        /// has not already been initialized.
        /// A reference to a boolean that determines whether the target has already 
        /// been initialized.
        /// A reference to an object used as the mutually exclusive lock for initializing
        /// .
        /// The initialized value of type . 
        public static T EnsureInitialized(ref T target, ref bool initialized, ref object syncLock)
        { 
            // Fast path. 
            if (initialized)
            { 
                object barrierGarbage = s_barrier; // Insert a volatile load barrier. Needed on IA64.
                return target;
            }
 
            return EnsureInitializedCore(ref target, ref initialized, ref syncLock, LazyHelpers.s_activatorFactorySelector);
        } 
 
        /// 
        /// Initializes a target reference or value type with a specified function if it has not already been 
        /// initialized.
        /// 
        /// The type of the reference to be initialized.
        /// A reference or value of type  to initialize if it 
        /// has not already been initialized.
        /// A reference to a boolean that determines whether the target has already 
        /// been initialized. 
        /// A reference to an object used as the mutually exclusive lock for initializing
        /// . 
        /// The  invoked to initialize the
        /// reference or value.
        /// The initialized value of type .
        public static T EnsureInitialized(ref T target, ref bool initialized, ref object syncLock, Func valueFactory) 
        {
            // Fast path. 
            if (initialized) 
            {
                object barrierGarbage = s_barrier; // Insert a volatile load barrier. Needed on IA64. 
                return target;
            }

            return EnsureInitializedCore(ref target, ref initialized, ref syncLock, valueFactory); 
        }
 
        ///  
        /// Ensure the target is initialized and return the value (slow path). This overload permits nulls
        /// and also works for value type targets. Uses the supplied function to create the value. 
        /// 
        /// The type of target.
        /// A reference to the target to be initialized.
        /// A reference to a location tracking whether the target has been initialized. 
        /// A reference to a location containing a mutual exclusive lock.
        ///  
        /// The  to invoke in order to produce the lazily-initialized value. 
        /// 
        /// The initialized object. 
        private static T EnsureInitializedCore(ref T target, ref bool initialized, ref object syncLock, Func valueFactory)
        {
            // Lazily initialize the lock if necessary.
            object slock = syncLock; 
            if (slock == null)
            { 
                object newLock = new object(); 
                slock = Interlocked.CompareExchange(ref syncLock, newLock, null);
                if (slock == null) 
                {
                    slock = newLock;
                }
            } 

            // Now double check that initialization is still required. 
            lock (slock) 
            {
                if (!initialized) 
                {
                    target = valueFactory();
                    initialized = true;
                } 
            }
 
            return target; 
        }
 
        // Caches the activation selector function to avoid delegate allocations.
        private static class LazyHelpers
        {
            internal static Func s_activatorFactorySelector = new Func(ActivatorFactorySelector); 

            private static T ActivatorFactorySelector() 
            { 
                try
                { 
                    return (T)Activator.CreateInstance(typeof(T));
                }
                catch (MissingMethodException)
                { 
                    throw new MissingMemberException(Environment.GetResourceString("Lazy_CreateValue_NoParameterlessCtorForT"));
                } 
            } 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK