Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Lazy.cs / 1305376 / Lazy.cs
#pragma warning disable 0420 // ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== // =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ // // Lazy.cs // //[....] // // A class that provides a simple, lightweight implementation of lazy initialization, // obviating the need for a developer to implement a custom, thread-safe lazy initialization // solution. // // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- using System.Runtime; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Diagnostics; using System.Runtime.Serialization; using System.Threading; using System.Diagnostics.Contracts; namespace System { ////// Provides support for lazy initialization. /// ///Specifies the type of element being laziliy initialized. ////// [Serializable] [ComVisible(false)] [HostProtection(Synchronization = true, ExternalThreading = true)] [DebuggerTypeProxy(typeof(System_LazyDebugView<>))] [DebuggerDisplay("ThreadSafetyMode={Mode}, IsValueCreated={IsValueCreated}, IsValueFaulted={IsValueFaulted}, Value={ValueForDebugDisplay}")] public class Lazy/// By default, all public and protected members of ///are thread-safe and may be used /// concurrently from multiple threads. These thread-safety guarantees may be removed optionally and per instance /// using parameters to the type's constructors. /// { #region Inner classes /// /// wrapper class to box the initialized value, this is mainly created to avoid boxing/unboxing the value each time the value is called in case T is /// a value type /// [Serializable] class Boxed { internal Boxed(T value) { m_value = value; } internal T m_value; } ////// Wrapper class to wrap the excpetion thrown by the value factory /// class LazyInternalExceptionHolder { internal Exception m_exception; internal LazyInternalExceptionHolder(Exception ex) { m_exception = ex; } } #endregion // A dummy delegate used as a : // 1- Flag to avoid recursive call to Value in None and ExecutionAndPublication modes in m_valueFactory // 2- Flag to PublicationOnly mode in m_threadSafeObj static FuncPUBLICATION_ONLY_OR_ALREADY_INITIALIZED = delegate { return default(T); }; //null --> value is not created //m_value is Boxed --> the value is created, and m_value holds the value //m_value is LazyExceptionHolder --> it holds an exception private volatile object m_boxed; // The factory delegate that returns the value. // In None and ExecutionAndPublication modes, this will be set to PUBLICATION_ONLY_OR_ALREADY_INITIALIZED as a flag to avoid recursive calls [NonSerialized] private Func m_valueFactory; // null if it is not thread safe mode // PUBLICATION_ONLY_OR_ALREADY_INITIALIZED if PublicationOnly mode // object if ExecutionAndPublication mode [NonSerialized] private readonly object m_threadSafeObj; /// /// Initializes a new instance of the ///class that /// uses 's default constructor for lazy initialization. /// /// An instance created with this constructor may be used concurrently from multiple threads. /// public Lazy() : this(LazyThreadSafetyMode.ExecutionAndPublication) { } ////// Initializes a new instance of the /// /// Theclass that uses a /// specified initialization function. /// invoked to produce the lazily-initialized value when it is /// needed. /// /// /// is a null /// reference (Nothing in Visual Basic). /// An instance created with this constructor may be used concurrently from multiple threads. /// public Lazy(FuncvalueFactory) : this(valueFactory, LazyThreadSafetyMode.ExecutionAndPublication) { } /// /// Initializes a new instance of the /// true if this instance should be usable by multiple threads concurrently; false if the instance will only be used by one thread at a time. /// public Lazy(bool isThreadSafe) : this(isThreadSafe? LazyThreadSafetyMode.ExecutionAndPublication : LazyThreadSafetyMode.None) { } ////// class that uses 's default constructor and a specified thread-safety mode. /// /// Initializes a new instance of the /// The lazy thread-safety mode mode ////// class that uses 's default constructor and a specified thread-safety mode. /// public Lazy(LazyThreadSafetyMode mode) { m_threadSafeObj = GetObjectFromMode(mode); } /// mode contains an invalid valuee /// Initializes a new instance of the /// /// Theclass /// that uses a specified initialization function and a specified thread-safety mode. /// invoked to produce the lazily-initialized value when it is needed. /// /// true if this instance should be usable by multiple threads concurrently; false if the instance will only be used by one thread at a time. /// /// public Lazy(Func is /// a null reference (Nothing in Visual Basic). valueFactory, bool isThreadSafe) : this(valueFactory, isThreadSafe ? LazyThreadSafetyMode.ExecutionAndPublication : LazyThreadSafetyMode.None) { } /// /// Initializes a new instance of the /// /// Theclass /// that uses a specified initialization function and a specified thread-safety mode. /// invoked to produce the lazily-initialized value when it is needed. /// /// The lazy thread-safety mode. /// /// is /// a null reference (Nothing in Visual Basic). public Lazy(Func mode contains an invalid value. valueFactory, LazyThreadSafetyMode mode) { if (valueFactory == null) throw new ArgumentNullException("valueFactory"); m_threadSafeObj = GetObjectFromMode(mode); m_valueFactory = valueFactory; } /// /// Static helper function that returns an object based on the given mode. it also throws an exception if the mode is invalid /// private static object GetObjectFromMode(LazyThreadSafetyMode mode) { if (mode == LazyThreadSafetyMode.ExecutionAndPublication) return new object(); else if (mode == LazyThreadSafetyMode.PublicationOnly) return PUBLICATION_ONLY_OR_ALREADY_INITIALIZED; else if (mode != LazyThreadSafetyMode.None) throw new ArgumentOutOfRangeException("mode", Environment.GetResourceString("Lazy_ctor_ModeInvalid")); return null; // None mode } ///Forces initialization during serialization. /// The StreamingContext for the serialization operation. [OnSerializing] private void OnSerializing(StreamingContext context) { // Force initialization T dummy = Value; } ///Creates and returns a string representation of this instance. ///The result of calling ///on the . /// The public override string ToString() { return IsValueCreated ? Value.ToString() : Environment.GetResourceString("Lazy_ToString_ValueNotCreated"); } ///is null. /// Gets the value of the Lazy<T> for debugging display purposes. internal T ValueForDebugDisplay { get { if (!IsValueCreated) { return default(T); } return ((Boxed)m_boxed).m_value; } } ////// Gets a value indicating whether this instance may be used concurrently from multiple threads. /// internal LazyThreadSafetyMode Mode { get { if (m_threadSafeObj == null) return LazyThreadSafetyMode.None; if (m_threadSafeObj == (object)PUBLICATION_ONLY_OR_ALREADY_INITIALIZED) return LazyThreadSafetyMode.PublicationOnly; return LazyThreadSafetyMode.ExecutionAndPublication; } } ////// Gets whether the value creation is faulted or not /// internal bool IsValueFaulted { get { return m_boxed is LazyInternalExceptionHolder; } } ///Gets a value indicating whether the ///has been initialized. /// true if the ///instance has been initialized; /// otherwise, false. /// The initialization of a public bool IsValueCreated { #if !FEATURE_CORECLR && !PFX_LEGACY_3_5 [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] #endif get { return m_boxed != null && m_boxed is Boxed; } } ///instance may result in either /// a value being produced or an exception being thrown. If an exception goes unhandled during initialization, /// the instance is still considered initialized, and that exception /// will be thrown on subsequent accesses to . In such cases, /// will return true. /// Gets the lazily initialized value of the current ///. The lazily initialized value of the current ///. /// The ///was initialized to use the default constructor /// of the type being lazily initialized, and that type does not have a public, parameterless constructor. /// /// The ///was initialized to use the default constructor /// of the type being lazily initialized, and permissions to access the constructor were missing. /// /// The ///was constructed with the or /// and the initialization function attempted to access on this instance. /// /// If [DebuggerBrowsable(DebuggerBrowsableState.Never)] public T Value { get { Boxed boxed = null; if (m_boxed != null ) { // Do a quick check up front for the fast path. boxed = m_boxed as Boxed; if (boxed != null) { return boxed.m_value; } LazyInternalExceptionHolder exc = m_boxed as LazyInternalExceptionHolder; Contract.Assert(m_boxed != null); throw exc.m_exception; } // Fall through to the slow path. // We call NOCTD to abort attempts by the debugger to funceval this property (e.g. on mouseover) // (the debugger proxy is the correct way to look at state/value of this object) #if !PFX_LEGACY_3_5 Debugger.NotifyOfCrossThreadDependency(); #endif return LazyInitValue(); } } ///is false, accessing will force initialization. /// Please for more information on how will behave if an exception is thrown /// from initialization delegate. /// /// local helper method to initialize the value /// ///The inititialized T value private T LazyInitValue() { Boxed boxed = null; LazyThreadSafetyMode mode = Mode; if (mode == LazyThreadSafetyMode.None) { boxed = CreateValue(); m_boxed = boxed; } else if (mode == LazyThreadSafetyMode.PublicationOnly) { boxed = CreateValue(); if (Interlocked.CompareExchange(ref m_boxed, boxed, null) != null) boxed = (Boxed)m_boxed; // set the boxed value to the succeeded thread value } else { lock (m_threadSafeObj) { if (m_boxed == null) { boxed = CreateValue(); m_boxed = boxed; } else // got the lock but the value is not null anymore, check if it is created by another thread or faulted and throw if so { boxed = m_boxed as Boxed; if (boxed == null) // it is not Boxed, so it is a LazyInternalExceptionHolder { LazyInternalExceptionHolder exHolder = m_boxed as LazyInternalExceptionHolder; Contract.Assert(exHolder != null); throw exHolder.m_exception; } } } } Contract.Assert(boxed != null); return boxed.m_value; } ///Creates an instance of T using m_valueFactory in case its not null or use reflection to create a new T() ///An instance of Boxed. private Boxed CreateValue() { Boxed boxed = null; LazyThreadSafetyMode mode = Mode; if (m_valueFactory != null) { try { // check for recursion if (mode != LazyThreadSafetyMode.PublicationOnly && m_valueFactory == PUBLICATION_ONLY_OR_ALREADY_INITIALIZED) throw new InvalidOperationException(Environment.GetResourceString("Lazy_Value_RecursiveCallsToValue")); Funcfactory = m_valueFactory; if (mode != LazyThreadSafetyMode.PublicationOnly) // only detect recursion on None and ExecutionAndPublication modes m_valueFactory = PUBLICATION_ONLY_OR_ALREADY_INITIALIZED; boxed = new Boxed(factory()); } catch (Exception ex) { if (mode != LazyThreadSafetyMode.PublicationOnly) // don't cache the exception for PublicationOnly mode { #if PFX_LEGACY_3_5 m_boxed = new LazyInternalExceptionHolder(ex); #else m_boxed = new LazyInternalExceptionHolder(ex.PrepForRemoting());// copy the call stack by calling the internal method PrepForRemoting #endif } throw; } } else { try { boxed = new Boxed((T)Activator.CreateInstance(typeof(T))); } catch (System.MissingMethodException) { Exception ex = new System.MissingMemberException(Environment.GetResourceString("Lazy_CreateValue_NoParameterlessCtorForT")); if (mode != LazyThreadSafetyMode.PublicationOnly) // don't cache the exception for PublicationOnly mode m_boxed = new LazyInternalExceptionHolder(ex); throw ex; } } return boxed; } } /// A debugger view of the Lazy<T> to surface additional debugging properties and /// to ensure that the Lazy<T> does not become initialized if it was not already. internal sealed class System_LazyDebugView{ //The Lazy object being viewed. private readonly Lazy m_lazy; /// Constructs a new debugger view object for the provided Lazy object. /// A Lazy object to browse in the debugger. public System_LazyDebugView(Lazylazy) { m_lazy = lazy; } /// Returns whether the Lazy object is initialized or not. public bool IsValueCreated { get { return m_lazy.IsValueCreated; } } ///Returns the value of the Lazy object. public T Value { get { return m_lazy.ValueForDebugDisplay; } } ///Returns the execution mode of the Lazy object public LazyThreadSafetyMode Mode { get { return m_lazy.Mode; } } ///Returns the execution mode of the Lazy object public bool IsValueFaulted { get { return m_lazy.IsValueFaulted; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- StringResourceManager.cs
- AsymmetricSignatureFormatter.cs
- UIElementCollection.cs
- ChannelDispatcher.cs
- AdornerHitTestResult.cs
- ExtensionSurface.cs
- WebConfigurationHost.cs
- OutputCache.cs
- Peer.cs
- XomlCompilerParameters.cs
- StagingAreaInputItem.cs
- SearchForVirtualItemEventArgs.cs
- ScriptServiceAttribute.cs
- SingleStorage.cs
- SqlDataSourceCustomCommandEditor.cs
- ParameterModifier.cs
- ProxyHelper.cs
- AnnotationDocumentPaginator.cs
- SchemaDeclBase.cs
- ByteStack.cs
- isolationinterop.cs
- FieldNameLookup.cs
- HMAC.cs
- TypeBrowser.xaml.cs
- View.cs
- SafePointer.cs
- AdCreatedEventArgs.cs
- RectangleHotSpot.cs
- typedescriptorpermission.cs
- EntityTypeBase.cs
- ItemMap.cs
- ChainedAsyncResult.cs
- ComNativeDescriptor.cs
- DelayedRegex.cs
- SQLInt16.cs
- BufferedStream2.cs
- ProcessHostConfigUtils.cs
- Wrapper.cs
- NameValuePair.cs
- DocumentViewerHelper.cs
- DiscoveryEndpointElement.cs
- DataServiceRequest.cs
- safesecurityhelperavalon.cs
- ComboBoxRenderer.cs
- Help.cs
- StylusOverProperty.cs
- PersonalizationState.cs
- UiaCoreProviderApi.cs
- ContextInformation.cs
- DeferredBinaryDeserializerExtension.cs
- CompilerScope.cs
- WpfPayload.cs
- PassportAuthenticationModule.cs
- SystemTcpConnection.cs
- AsymmetricKeyExchangeFormatter.cs
- COM2PropertyPageUITypeConverter.cs
- CompilerError.cs
- StorageModelBuildProvider.cs
- TableItemPatternIdentifiers.cs
- CompilationLock.cs
- WindowsListViewScroll.cs
- FixedHyperLink.cs
- EventItfInfo.cs
- LineVisual.cs
- BamlMapTable.cs
- ImportCatalogPart.cs
- TransformGroup.cs
- LoginName.cs
- DataGridRowClipboardEventArgs.cs
- LoginName.cs
- HistoryEventArgs.cs
- Module.cs
- EpmHelper.cs
- RIPEMD160Managed.cs
- GroupBoxAutomationPeer.cs
- PlanCompiler.cs
- CellCreator.cs
- ListViewItemMouseHoverEvent.cs
- XmlProcessingInstruction.cs
- LayoutInformation.cs
- XmlSchemaValidator.cs
- ExpressionBinding.cs
- SubpageParagraph.cs
- FixUp.cs
- Shape.cs
- WindowsImpersonationContext.cs
- StdValidatorsAndConverters.cs
- TemplateControlParser.cs
- StructuralType.cs
- HtmlInputPassword.cs
- EmptyReadOnlyDictionaryInternal.cs
- ClientScriptManager.cs
- GraphicsPathIterator.cs
- KeyboardEventArgs.cs
- SplineKeyFrames.cs
- DataContractFormatAttribute.cs
- PropertiesTab.cs
- XmlTypeMapping.cs
- LineGeometry.cs
- RedirectionProxy.cs