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(Func function, 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(Func function, 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
- CodeTypeMember.cs
- MouseWheelEventArgs.cs
- WsdlInspector.cs
- SafeArrayTypeMismatchException.cs
- DbUpdateCommandTree.cs
- TypeSystemProvider.cs
- FlowDocumentFormatter.cs
- TranslateTransform3D.cs
- StyleCollection.cs
- AllMembershipCondition.cs
- CategoryGridEntry.cs
- CallbackTimeoutsBehavior.cs
- SplineQuaternionKeyFrame.cs
- MessageSmuggler.cs
- SqlVersion.cs
- ShadowGlyph.cs
- IconConverter.cs
- MessageSecurityOverHttpElement.cs
- VersionUtil.cs
- RecognizeCompletedEventArgs.cs
- DetailsViewPageEventArgs.cs
- COM2Enum.cs
- XsltInput.cs
- wmiprovider.cs
- SwitchLevelAttribute.cs
- OpCodes.cs
- QueryCacheEntry.cs
- ControlEvent.cs
- relpropertyhelper.cs
- ResourceDescriptionAttribute.cs
- QilInvokeEarlyBound.cs
- TransportSecurityBindingElement.cs
- FlagsAttribute.cs
- SurrogateDataContract.cs
- QueryOpcode.cs
- BaseTreeIterator.cs
- DBSqlParserTableCollection.cs
- UrlMapping.cs
- SizeKeyFrameCollection.cs
- ClassHandlersStore.cs
- ConfigurationStrings.cs
- OutOfMemoryException.cs
- FillErrorEventArgs.cs
- StringSorter.cs
- SynchronizationLockException.cs
- InvalidProgramException.cs
- BitmapEffect.cs
- SecurityPolicySection.cs
- DataProviderNameConverter.cs
- NamespaceDecl.cs
- BindableAttribute.cs
- OptimalBreakSession.cs
- SendAgentStatusRequest.cs
- ValidationRuleCollection.cs
- ObjectPersistData.cs
- RelOps.cs
- ComponentResourceKeyConverter.cs
- HtmlControlPersistable.cs
- OutputCacheProfileCollection.cs
- SecurityContextSecurityTokenResolver.cs
- SimpleNameService.cs
- AudioBase.cs
- StorageTypeMapping.cs
- XmlChildNodes.cs
- HelpProvider.cs
- OleDbException.cs
- ObjectPersistData.cs
- RecipientInfo.cs
- ValidationService.cs
- Columns.cs
- coordinatorscratchpad.cs
- ContentValidator.cs
- URIFormatException.cs
- StorageAssociationTypeMapping.cs
- TableLayoutPanelBehavior.cs
- Keyboard.cs
- SourceFileInfo.cs
- ExtensionDataObject.cs
- Comparer.cs
- ScriptReferenceEventArgs.cs
- ConditionCollection.cs
- XComponentModel.cs
- OneWayBindingElementImporter.cs
- AcceptorSessionSymmetricMessageSecurityProtocol.cs
- MenuItemStyleCollection.cs
- TraceEventCache.cs
- UnsafeNativeMethods.cs
- DataPagerField.cs
- DateTimeOffsetConverter.cs
- XamlReader.cs
- SamlSubjectStatement.cs
- COM2IDispatchConverter.cs
- PropertyChangeTracker.cs
- coordinatorfactory.cs
- TreeNodeEventArgs.cs
- DeviceContexts.cs
- Latin1Encoding.cs
- EdmConstants.cs
- DocumentPageTextView.cs
- XmlAnyElementAttributes.cs