public void WeakReferenceExtensions_ArgumentChecking() { #pragma warning disable IDE0034 // Simplify 'default' expression (illustrative of method signature) Assert.ThrowsException <ArgumentNullException>(() => WeakReferenceExtensions.GetTarget(default(WeakReference <string>))); Assert.ThrowsException <ArgumentNullException>(() => WeakReferenceExtensions.GetOrSetTarget(default(WeakReference <string>), () => "")); Assert.ThrowsException <ArgumentNullException>(() => WeakReferenceExtensions.GetOrSetTarget(new WeakReference <string>(""), default(Func <string>))); #pragma warning restore IDE0034 // Simplify 'default' expression }
public Cache(Func <T, R> function, Func <IMemoizationCacheEntryMetrics, TMetric> ranker, int maxCapacity, bool descending, double ageThreshold, bool cacheError, IStopwatchFactory stopwatchFactory) { _function = args => { var weakArgs = WeakReferenceExtensions.Create(args); var invokeDuration = default(TimeSpan); #if DEBUG Interlocked.Increment(ref _invocationCount); #endif Trim(); var res = default(IMetricsCacheEntry <WeakReference <T>, R>); try { var swInvokeStart = _stopwatch.ElapsedTicks; var value = function(args); invokeDuration = new TimeSpan(_stopwatch.ElapsedTicks - swInvokeStart); res = new MetricsValueCacheEntry <WeakReference <T>, R>(weakArgs, value); } catch (Exception ex) when(_cacheError) { res = new MetricsErrorCacheEntry <WeakReference <T>, R>(weakArgs, ex); } res.CreationTime = new TimeSpan(_stopwatch.ElapsedTicks); res.InvokeDuration = invokeDuration; _lock.EnterWriteLock(); try { _entries.Add(res); } finally { _lock.ExitWriteLock(); } return(res); }; _cache = new WeakCacheDictionary <T, IMetricsCacheEntry <WeakReference <T>, R> >(); _lock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); _entries = new HashSet <IMetricsCacheEntry <WeakReference <T>, R> >(); _stopwatch = stopwatchFactory.StartNew(); // // Exclude newest items which have statically irrelevant data, so they get a chance to become relevant. // var candidates = _entries.OrderBy(e => _stopwatch.ElapsedTicks - e.CreationTime.Ticks).Take(Math.Max(1, (int)(maxCapacity * ageThreshold))); _ranker = descending ? candidates.OrderByDescending(e => ranker(e)) : candidates.OrderBy(e => ranker(e)); _maxCapacity = maxCapacity; _cacheError = cacheError; }
public void WeakReferenceExtensions_Create_Null() { var w = WeakReferenceExtensions.Create <string>(target: null); Assert.IsFalse(w.TryGetTarget(out _)); Assert.IsNull(w.GetTarget()); Assert.IsNull(w.GetOrSetTarget(() => { Assert.Fail(); return(""); })); }
private static WeakReference <string> CreateWeakString() { var s = GetString(); var w = WeakReferenceExtensions.Create <string>(s); Assert.AreSame(s, w.GetTarget()); GC.KeepAlive(s); return(w); }
public void WeakReferenceExtensions_Create_Alive() { var s = "bar".ToUpper(); var w = WeakReferenceExtensions.Create <string>(s); Assert.IsTrue(w.TryGetTarget(out string target)); Assert.AreSame(s, target); Assert.AreSame(s, w.GetTarget()); Assert.AreSame(s, w.GetOrSetTarget(() => { Assert.Fail(); return(""); })); GC.KeepAlive(s); }
public Cache(Func <T, R> function, int maxCapacity, bool cacheError) { _function = args => { var weakArgs = WeakReferenceExtensions.Create(args); #if DEBUG var invokeDuration = default(TimeSpan); Interlocked.Increment(ref _invocationCount); #endif Trim(); var res = default(ILruCacheEntry <WeakReference <T>, R>); try { #if DEBUG var swInvoke = Stopwatch.StartNew(); #endif var value = function(args); #if DEBUG invokeDuration = swInvoke.Elapsed; #endif res = new LruValueCacheEntry <WeakReference <T>, R>(weakArgs, value); } catch (Exception ex) when(_cacheError) { res = new LruErrorCacheEntry <WeakReference <T>, R>(weakArgs, ex); } Interlocked.Increment(ref _count); #if DEBUG res.GetMetrics().InvokeDuration = invokeDuration; #endif return(res); }; _cache = new WeakCacheDictionary <T, ILruCacheEntry <WeakReference <T>, R> >(); _lock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); _maxCapacity = maxCapacity; _cacheError = cacheError; }