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
- DataFieldConverter.cs
- DataGridViewRowDividerDoubleClickEventArgs.cs
- SQLInt16Storage.cs
- SelectionWordBreaker.cs
- ValidationPropertyAttribute.cs
- SimpleBitVector32.cs
- DesignTable.cs
- SchemaComplexType.cs
- ScriptBehaviorDescriptor.cs
- DataRelationPropertyDescriptor.cs
- SamlAssertion.cs
- VersionedStream.cs
- MatrixStack.cs
- DocumentViewer.cs
- Pair.cs
- DocumentOrderComparer.cs
- AuthenticationException.cs
- prefixendpointaddressmessagefiltertable.cs
- AdapterDictionary.cs
- SecurityContextSecurityToken.cs
- WSSecurityXXX2005.cs
- ResourceManagerWrapper.cs
- ImportContext.cs
- DataGridTextBoxColumn.cs
- TypefaceMetricsCache.cs
- MediaElementAutomationPeer.cs
- Message.cs
- CodeIterationStatement.cs
- TrustManagerPromptUI.cs
- PropertyChangedEventManager.cs
- DataGrid.cs
- ContextConfiguration.cs
- XmlDictionaryString.cs
- ItemChangedEventArgs.cs
- DynamicArgumentDesigner.xaml.cs
- DrawingContextWalker.cs
- ChangeNode.cs
- Axis.cs
- HyperLinkField.cs
- DataGridViewTopRowAccessibleObject.cs
- GenericRootAutomationPeer.cs
- CompareValidator.cs
- DataGridViewBand.cs
- AttachedAnnotationChangedEventArgs.cs
- CodeTypeOfExpression.cs
- DesignerDataSchemaClass.cs
- XmlSchemaComplexType.cs
- ImageSource.cs
- AssemblyCache.cs
- WebPartConnectionsEventArgs.cs
- Lease.cs
- GiveFeedbackEvent.cs
- ElapsedEventArgs.cs
- ViewgenContext.cs
- HtmlUtf8RawTextWriter.cs
- RangeValidator.cs
- CodeTypeDeclarationCollection.cs
- BaseCodeDomTreeGenerator.cs
- DesignTimeTemplateParser.cs
- CodeCompiler.cs
- UserNameSecurityTokenProvider.cs
- DetectEofStream.cs
- WindowAutomationPeer.cs
- BinaryReader.cs
- StringUtil.cs
- RawTextInputReport.cs
- DefaultValueConverter.cs
- ArgumentOutOfRangeException.cs
- MultipartContentParser.cs
- PrePostDescendentsWalker.cs
- CompositeKey.cs
- TemplateLookupAction.cs
- CommandID.cs
- GroupBoxRenderer.cs
- DateTime.cs
- UIPermission.cs
- NGCSerializerAsync.cs
- OptimizedTemplateContent.cs
- ZipIOZip64EndOfCentralDirectoryBlock.cs
- ButtonColumn.cs
- GeneralTransform3DGroup.cs
- oledbmetadatacollectionnames.cs
- ReferencedAssembly.cs
- ServerIdentity.cs
- DesigntimeLicenseContextSerializer.cs
- HebrewNumber.cs
- RectIndependentAnimationStorage.cs
- LineInfo.cs
- DataGridHyperlinkColumn.cs
- ValueTypeFixupInfo.cs
- TabPage.cs
- IdentityNotMappedException.cs
- TreeNodeBindingCollection.cs
- ToggleButton.cs
- FixedBufferAttribute.cs
- EditorPartCollection.cs
- VisualTreeHelper.cs
- StoreAnnotationsMap.cs
- Vertex.cs
- PenContext.cs