Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Common / Utils / Memoizer.cs / 1305376 / 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
- RegexMatch.cs
- DesignerOptions.cs
- StackBuilderSink.cs
- _ConnectionGroup.cs
- ReadOnlyDictionary.cs
- SmiConnection.cs
- FacetChecker.cs
- SchemaElementDecl.cs
- DbMetaDataFactory.cs
- StrokeRenderer.cs
- WsdlImporterElement.cs
- ReadWriteObjectLock.cs
- WindowsPen.cs
- TraceSource.cs
- RawStylusSystemGestureInputReport.cs
- BamlLocalizerErrorNotifyEventArgs.cs
- ColumnBinding.cs
- NTAccount.cs
- NetPipeSectionData.cs
- HwndHostAutomationPeer.cs
- KeyInstance.cs
- DiscoveryMessageSequence11.cs
- Vector3dCollection.cs
- HorizontalAlignConverter.cs
- SmtpLoginAuthenticationModule.cs
- GroupBox.cs
- BamlRecordHelper.cs
- SHA256Managed.cs
- SQLDoubleStorage.cs
- StateMachineSubscription.cs
- COM2PictureConverter.cs
- FullTextLine.cs
- ContourSegment.cs
- SessionStateSection.cs
- KeyToListMap.cs
- MailMessage.cs
- IPeerNeighbor.cs
- EastAsianLunisolarCalendar.cs
- MatrixIndependentAnimationStorage.cs
- UpdateEventArgs.cs
- EnumValAlphaComparer.cs
- MouseEvent.cs
- FontSizeConverter.cs
- WriterOutput.cs
- TypeNameConverter.cs
- FormatConvertedBitmap.cs
- HttpResponseHeader.cs
- MethodImplAttribute.cs
- Object.cs
- ModuleBuilder.cs
- DesignerFrame.cs
- CustomErrorCollection.cs
- MappingSource.cs
- FrameworkElementFactoryMarkupObject.cs
- HttpProfileBase.cs
- Shared.cs
- FunctionImportMapping.cs
- ColorTransformHelper.cs
- Rss20FeedFormatter.cs
- TypeRestriction.cs
- BlobPersonalizationState.cs
- UnsafeNativeMethods.cs
- SystemIPInterfaceStatistics.cs
- XmlTextReader.cs
- XsdDataContractImporter.cs
- DataTemplateSelector.cs
- DocumentPage.cs
- FileSystemEventArgs.cs
- Invariant.cs
- RequestCacheEntry.cs
- ReverseInheritProperty.cs
- Cursors.cs
- ListViewDataItem.cs
- InvalidAsynchronousStateException.cs
- PropertyBuilder.cs
- WindowsListViewItemStartMenu.cs
- MediaContextNotificationWindow.cs
- BaseCollection.cs
- DataSourceCacheDurationConverter.cs
- KernelTypeValidation.cs
- GeneralTransform2DTo3DTo2D.cs
- FamilyTypefaceCollection.cs
- GridViewAutomationPeer.cs
- ComponentChangingEvent.cs
- TrueReadOnlyCollection.cs
- SplayTreeNode.cs
- StrongNamePublicKeyBlob.cs
- QueryContinueDragEvent.cs
- ProxyWebPartManager.cs
- UriParserTemplates.cs
- XmlSchemaElement.cs
- MobileControlDesigner.cs
- KeyNotFoundException.cs
- CompilerScope.cs
- StylusCollection.cs
- TranslateTransform3D.cs
- FamilyMap.cs
- TemplatedWizardStep.cs
- NavigationProperty.cs
- AttributeTable.cs