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
- DrawListViewItemEventArgs.cs
- LinqExpressionNormalizer.cs
- InfoCardBaseException.cs
- WebBrowserContainer.cs
- BuildManagerHost.cs
- SystemDropShadowChrome.cs
- DataBoundControlAdapter.cs
- CapabilitiesSection.cs
- WebPartConnectionsCancelVerb.cs
- KeyTime.cs
- PermissionToken.cs
- RtfToXamlLexer.cs
- Trace.cs
- Translator.cs
- ChannelSinkStacks.cs
- TcpDuplicateContext.cs
- ButtonStandardAdapter.cs
- HttpRuntime.cs
- FullTrustAssembly.cs
- HostingEnvironment.cs
- QueueProcessor.cs
- SQLRoleProvider.cs
- BindingManagerDataErrorEventArgs.cs
- RegionIterator.cs
- ConfigXmlAttribute.cs
- CompiledAction.cs
- Parser.cs
- ComplexPropertyEntry.cs
- LockRecursionException.cs
- StatusStrip.cs
- CopyNodeSetAction.cs
- CorrelationExtension.cs
- SQLInt16Storage.cs
- SimpleApplicationHost.cs
- WindowsFormsSectionHandler.cs
- CapabilitiesAssignment.cs
- EventLogPermission.cs
- TraceHandler.cs
- EventHandlerList.cs
- DataServiceException.cs
- DBSqlParserColumnCollection.cs
- StructuredTypeInfo.cs
- SelectionPattern.cs
- DataGridViewComboBoxEditingControl.cs
- TreeNodeSelectionProcessor.cs
- Journal.cs
- KoreanLunisolarCalendar.cs
- Classification.cs
- ClientBuildManager.cs
- NamespaceMapping.cs
- IndexedEnumerable.cs
- SoapIgnoreAttribute.cs
- GeometryDrawing.cs
- XmlCDATASection.cs
- odbcmetadatacolumnnames.cs
- TextBox.cs
- SymLanguageVendor.cs
- EntityContainer.cs
- SocketAddress.cs
- WebPartZoneAutoFormat.cs
- FilterableAttribute.cs
- FunctionCommandText.cs
- rsa.cs
- PolicyConversionContext.cs
- InputGestureCollection.cs
- GuidelineCollection.cs
- XDRSchema.cs
- ApplicationDirectoryMembershipCondition.cs
- DataStorage.cs
- storagemappingitemcollection.viewdictionary.cs
- DependencyPropertyKey.cs
- BooleanFunctions.cs
- DesignerEventService.cs
- EventProvider.cs
- StateDesigner.LayoutSelectionGlyph.cs
- FontCacheLogic.cs
- RealProxy.cs
- WebServiceEnumData.cs
- Walker.cs
- COAUTHIDENTITY.cs
- ScriptIgnoreAttribute.cs
- Item.cs
- RayMeshGeometry3DHitTestResult.cs
- Int32CollectionConverter.cs
- XmlSchemaIdentityConstraint.cs
- TextEncodedRawTextWriter.cs
- ModelItemDictionary.cs
- ToolBar.cs
- SmiEventStream.cs
- HttpHeaderCollection.cs
- SmtpTransport.cs
- DocumentAutomationPeer.cs
- ModuleBuilderData.cs
- XsdBuildProvider.cs
- StandardBindingCollectionElement.cs
- OleDbEnumerator.cs
- PeerToPeerException.cs
- XmlReader.cs
- EntityContainerEntitySet.cs
- DisplayClaim.cs