Skip to content

Commit

Permalink
IDisposable, no closure in GetOrAdd, Evicter debounce, fixes #1
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-jitbit committed Nov 9, 2022
1 parent 6749a7e commit ebef51e
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 5 deletions.
9 changes: 9 additions & 0 deletions FastCache.Benchmarks/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@ public void MemoryCacheLookup()
x = MemoryCache.Default["test987"];
}

[Benchmark]
public void FastCacheGetOrAdd()
{
_cache.GetOrAdd("test123", k => 123, TimeSpan.FromSeconds(1));
_cache.GetOrAdd("test234", k => 124, TimeSpan.FromSeconds(1));
_cache.GetOrAdd("test673", k => 125, TimeSpan.FromSeconds(1));
_cache.GetOrAdd("test987", k => 126, TimeSpan.FromSeconds(1));
}

[Benchmark]
public void FastCacheAddRemove()
{
Expand Down
35 changes: 30 additions & 5 deletions FastCache/FastCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Jitbit.Utils
/// <summary>
/// faster MemoryCache alternative. basically a concurrent dictionary with expiration
/// </summary>
public class FastCache<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
public class FastCache<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>, IDisposable
{
private readonly ConcurrentDictionary<TKey, TtlValue> _dict = new ConcurrentDictionary<TKey, TtlValue>();

Expand All @@ -25,10 +25,21 @@ public FastCache(int cleanupJobInterval = 10000)

void _EvictExpired(object state)
{
foreach (var p in _dict)
//overlapped execution? forget it, lets move on
if (Monitor.TryEnter(this))

This comment has been minimized.

Copy link
@theodorzoulias

theodorzoulias Nov 9, 2022

Take a look at this: ​​Why is lock(this) {...} bad? It applies to all Monitor methods as well, since the lock is based on Monitor.

This comment has been minimized.

Copy link
@alex-jitbit

alex-jitbit Nov 10, 2022

Author Member

@theodorzoulias fair point will address thaht in my next iteration

{
if (p.Value.IsExpired())
_dict.TryRemove(p.Key, out _);
try
{
foreach (var p in _dict)
{
if (p.Value.IsExpired())
_dict.TryRemove(p.Key, out _);
}
}
finally
{
Monitor.Exit(this);
}
}
}
}
Expand Down Expand Up @@ -137,7 +148,7 @@ public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory, TimeSpan ttl)
if (TryGet(key, out var value))
return value;

return _dict.GetOrAdd(key, k => new TtlValue(valueFactory(key), ttl)).Value;
return _dict.GetOrAdd(key, (k, v) => new TtlValue(valueFactory(k), v), ttl).Value;
}

/// <summary>
Expand Down Expand Up @@ -180,5 +191,19 @@ public bool IsExpired()
return difference > 0;
}
}

//IDispisable members
private bool _disposedValue;
public void Dispose() => Dispose(true);
protected virtual void Dispose(bool disposing)
{
if (!_disposedValue)
{
if (disposing)
_cleanUpTimer.Dispose();

_disposedValue = true;
}
}
}
}

0 comments on commit ebef51e

Please sign in to comment.