Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataEntity / System / Data / Common / Utils / Memoizer.cs / 2 / Memoizer.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....], [....] //--------------------------------------------------------------------- using System.Collections.Generic; using System.Threading; using System.Diagnostics; namespace System.Data.Common.Utils { ////// Remembers the result of evaluating an expensive function so that subsequent /// evaluations are faster. Thread-safe. /// ///Type of the argument to the function. ///Type of the function result. internal sealed class Memoizer{ private readonly Func _function; private readonly Dictionary _resultCache; private readonly ReaderWriterLockSlim _lock; /// /// Constructs /// /// Required. Function whose values are being cached. /// Optional. Comparer used to determine if two functions arguments /// are the same. internal Memoizer(Funcfunction, IEqualityComparer argComparer) { EntityUtil.CheckArgumentNull(function, "function"); _function = function; _resultCache = new Dictionary (argComparer); _lock = new ReaderWriterLockSlim(); } /// /// Evaluates the wrapped function for the given argument. If the function has already /// been evaluated for the given argument, returns cached value. Otherwise, the value /// is computed and returned. /// /// Function argument. ///Function result. internal TResult Evaluate(TArg arg) { Result result; bool hasResult; // check to see if a result has already been computed _lock.EnterReadLock(); try { hasResult = _resultCache.TryGetValue(arg, out result); } finally { _lock.ExitReadLock(); } if (!hasResult) { // compute the new value _lock.EnterWriteLock(); try { // see if the value has been computed in the interim if (!_resultCache.TryGetValue(arg, out result)) { result = new Result(() => _function(arg)); _resultCache.Add(arg, result); } } finally { _lock.ExitWriteLock(); } } // note: you need to release the global cache lock before (potentially) acquiring // a result lock in result.GetValue() return result.GetValue(); } ////// Encapsulates a 'deferred' result. The result is constructed with a delegate (must not /// be null) and when the user requests a value the delegate is invoked and stored. /// private class Result { private TResult _value; private Func_delegate; internal Result(Func createValueDelegate) { Debug.Assert(null != createValueDelegate, "delegate must be given"); _delegate = createValueDelegate; } internal TResult GetValue() { if (null == _delegate) { // if the delegate has been cleared, it means we have already computed the value return _value; } // lock the entry while computing the value so that two threads // don't simultaneously do the work lock (this) { if (null == _delegate) { // between our initial check and our acquisition of the lock, some other // thread may have computed the value return _value; } _value = _delegate(); // ensure _delegate (and its closure) is garbage collected, and set to null // to indicate that the value has been computed _delegate = null; return _value; } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....], [....] //--------------------------------------------------------------------- using System.Collections.Generic; using System.Threading; using System.Diagnostics; namespace System.Data.Common.Utils { ////// Remembers the result of evaluating an expensive function so that subsequent /// evaluations are faster. Thread-safe. /// ///Type of the argument to the function. ///Type of the function result. internal sealed class Memoizer{ private readonly Func _function; private readonly Dictionary _resultCache; private readonly ReaderWriterLockSlim _lock; /// /// Constructs /// /// Required. Function whose values are being cached. /// Optional. Comparer used to determine if two functions arguments /// are the same. internal Memoizer(Funcfunction, IEqualityComparer argComparer) { EntityUtil.CheckArgumentNull(function, "function"); _function = function; _resultCache = new Dictionary (argComparer); _lock = new ReaderWriterLockSlim(); } /// /// Evaluates the wrapped function for the given argument. If the function has already /// been evaluated for the given argument, returns cached value. Otherwise, the value /// is computed and returned. /// /// Function argument. ///Function result. internal TResult Evaluate(TArg arg) { Result result; bool hasResult; // check to see if a result has already been computed _lock.EnterReadLock(); try { hasResult = _resultCache.TryGetValue(arg, out result); } finally { _lock.ExitReadLock(); } if (!hasResult) { // compute the new value _lock.EnterWriteLock(); try { // see if the value has been computed in the interim if (!_resultCache.TryGetValue(arg, out result)) { result = new Result(() => _function(arg)); _resultCache.Add(arg, result); } } finally { _lock.ExitWriteLock(); } } // note: you need to release the global cache lock before (potentially) acquiring // a result lock in result.GetValue() return result.GetValue(); } ////// Encapsulates a 'deferred' result. The result is constructed with a delegate (must not /// be null) and when the user requests a value the delegate is invoked and stored. /// private class Result { private TResult _value; private Func_delegate; internal Result(Func createValueDelegate) { Debug.Assert(null != createValueDelegate, "delegate must be given"); _delegate = createValueDelegate; } internal TResult GetValue() { if (null == _delegate) { // if the delegate has been cleared, it means we have already computed the value return _value; } // lock the entry while computing the value so that two threads // don't simultaneously do the work lock (this) { if (null == _delegate) { // between our initial check and our acquisition of the lock, some other // thread may have computed the value return _value; } _value = _delegate(); // ensure _delegate (and its closure) is garbage collected, and set to null // to indicate that the value has been computed _delegate = null; return _value; } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SimplePropertyEntry.cs
- FreeFormDragDropManager.cs
- FormatException.cs
- SpeakProgressEventArgs.cs
- RectangleHotSpot.cs
- PaintValueEventArgs.cs
- versioninfo.cs
- SettingsPropertyNotFoundException.cs
- IsolationInterop.cs
- WindowsStatusBar.cs
- FileDetails.cs
- WebPartConnectionsCancelEventArgs.cs
- Set.cs
- ClientConvert.cs
- AttributeParameterInfo.cs
- SelectionItemPatternIdentifiers.cs
- ManifestSignedXml.cs
- RestHandlerFactory.cs
- TypeConstant.cs
- SHA512.cs
- ToolStripDropDownButton.cs
- DbConnectionStringCommon.cs
- assemblycache.cs
- HtmlInputRadioButton.cs
- Int32AnimationUsingKeyFrames.cs
- ZipIORawDataFileBlock.cs
- UnauthorizedAccessException.cs
- WindowShowOrOpenTracker.cs
- PluralizationServiceUtil.cs
- CompilerErrorCollection.cs
- TreeNodeEventArgs.cs
- DesignerSerializationOptionsAttribute.cs
- WebPartHelpVerb.cs
- CheckBox.cs
- AstTree.cs
- StandardCommands.cs
- RegisteredHiddenField.cs
- ISFTagAndGuidCache.cs
- Stream.cs
- _RequestCacheProtocol.cs
- PerformanceCounterLib.cs
- Stroke2.cs
- CustomErrorsSectionWrapper.cs
- GuidelineCollection.cs
- SchemaObjectWriter.cs
- IList.cs
- TraceListeners.cs
- RelationshipEndCollection.cs
- QilVisitor.cs
- TriggerCollection.cs
- ProcessHostFactoryHelper.cs
- HyperLinkColumn.cs
- MaskedTextProvider.cs
- SendDesigner.xaml.cs
- MonitoringDescriptionAttribute.cs
- VectorCollectionConverter.cs
- SourceCollection.cs
- StackOverflowException.cs
- EntityViewGenerationAttribute.cs
- Publisher.cs
- BuildDependencySet.cs
- ConnectionStringsExpressionBuilder.cs
- Compiler.cs
- BindValidationContext.cs
- SqlUserDefinedAggregateAttribute.cs
- Light.cs
- LingerOption.cs
- TargetParameterCountException.cs
- WeakReferenceList.cs
- ModelPerspective.cs
- ConnectionString.cs
- InlineObject.cs
- Parameter.cs
- TreeViewItemAutomationPeer.cs
- DetailsViewInsertEventArgs.cs
- ColumnBinding.cs
- Compilation.cs
- PropagatorResult.cs
- EntityDataSourceStatementEditor.cs
- DiscoveryDocumentSerializer.cs
- ArgumentNullException.cs
- HotSpot.cs
- SqlDataSourceFilteringEventArgs.cs
- Clock.cs
- SoapCodeExporter.cs
- CopyOnWriteList.cs
- DiscoveryClientDuplexChannel.cs
- SafeArrayTypeMismatchException.cs
- Border.cs
- TdsParserSessionPool.cs
- MailDefinition.cs
- unitconverter.cs
- ResourceDisplayNameAttribute.cs
- ColumnCollection.cs
- ProviderIncompatibleException.cs
- AssemblyBuilder.cs
- TextEndOfLine.cs
- SafeNativeMethods.cs
- TableProviderWrapper.cs
- XmlSchemaSimpleTypeRestriction.cs