Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataEntity / System / Data / Common / Utils / Memoizer.cs / 1 / 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
- StringCollection.cs
- Track.cs
- TreeNodeStyle.cs
- ChtmlPhoneCallAdapter.cs
- EastAsianLunisolarCalendar.cs
- WSHttpSecurity.cs
- AnnotationMap.cs
- BuilderInfo.cs
- ServiceEndpoint.cs
- ProxyFragment.cs
- DesignerSerializationManager.cs
- DefaultEvaluationContext.cs
- ManipulationStartingEventArgs.cs
- __ComObject.cs
- ClosableStream.cs
- VBIdentifierTrimConverter.cs
- SHA256Cng.cs
- Transform.cs
- DocumentGridContextMenu.cs
- TextureBrush.cs
- ValidatingPropertiesEventArgs.cs
- WebPartZoneDesigner.cs
- EvidenceBase.cs
- EmbossBitmapEffect.cs
- Registry.cs
- Frame.cs
- XDeferredAxisSource.cs
- HttpListenerTimeoutManager.cs
- DesignerAttribute.cs
- StandardBindingCollectionElement.cs
- InternalBase.cs
- XmlDataSource.cs
- Keywords.cs
- XmlLoader.cs
- MergeLocalizationDirectives.cs
- GridView.cs
- ExternalException.cs
- PartitionResolver.cs
- TrustManagerMoreInformation.cs
- OdbcConnection.cs
- SessionPageStateSection.cs
- EventSinkActivity.cs
- BamlStream.cs
- EventSourceCreationData.cs
- FunctionCommandText.cs
- EventListenerClientSide.cs
- KnownBoxes.cs
- DurableMessageDispatchInspector.cs
- PanelStyle.cs
- RelatedPropertyManager.cs
- EntityDataSourceContainerNameConverter.cs
- CustomWebEventKey.cs
- PageFunction.cs
- OrthographicCamera.cs
- GcHandle.cs
- ProcessingInstructionAction.cs
- GridEntryCollection.cs
- LineServices.cs
- LineSegment.cs
- RunWorkerCompletedEventArgs.cs
- ToolBarTray.cs
- GridViewDeleteEventArgs.cs
- CollectionBuilder.cs
- UriTemplate.cs
- CounterNameConverter.cs
- SafeReversePInvokeHandle.cs
- ResXBuildProvider.cs
- LocatorManager.cs
- HtmlShimManager.cs
- BehaviorEditorPart.cs
- WebPartConnectionsCloseVerb.cs
- SecureEnvironment.cs
- ViewStateModeByIdAttribute.cs
- UIElement3DAutomationPeer.cs
- Nodes.cs
- LayoutTable.cs
- EventBuilder.cs
- ObjectResult.cs
- DiffuseMaterial.cs
- TextRangeAdaptor.cs
- SerialPort.cs
- AncillaryOps.cs
- typedescriptorpermission.cs
- XmlValidatingReaderImpl.cs
- XmlSchemaSet.cs
- MediaPlayerState.cs
- TriState.cs
- CodeDefaultValueExpression.cs
- SapiRecoContext.cs
- StylusCaptureWithinProperty.cs
- SspiNegotiationTokenAuthenticator.cs
- DynamicResourceExtension.cs
- DecoratedNameAttribute.cs
- IncrementalHitTester.cs
- ExpandButtonVisibilityConverter.cs
- ApplicationSettingsBase.cs
- DataGridViewAutoSizeModeEventArgs.cs
- Rect3DConverter.cs
- PointLight.cs
- ByeMessageApril2005.cs