Skip to content

Commit ebef51e

Browse files
committed
IDisposable, no closure in GetOrAdd, Evicter debounce, fixes #1
1 parent 6749a7e commit ebef51e

File tree

2 files changed

+39
-5
lines changed

2 files changed

+39
-5
lines changed

FastCache.Benchmarks/Program.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ public void MemoryCacheLookup()
4141
x = MemoryCache.Default["test987"];
4242
}
4343

44+
[Benchmark]
45+
public void FastCacheGetOrAdd()
46+
{
47+
_cache.GetOrAdd("test123", k => 123, TimeSpan.FromSeconds(1));
48+
_cache.GetOrAdd("test234", k => 124, TimeSpan.FromSeconds(1));
49+
_cache.GetOrAdd("test673", k => 125, TimeSpan.FromSeconds(1));
50+
_cache.GetOrAdd("test987", k => 126, TimeSpan.FromSeconds(1));
51+
}
52+
4453
[Benchmark]
4554
public void FastCacheAddRemove()
4655
{

FastCache/FastCache.cs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace Jitbit.Utils
99
/// <summary>
1010
/// faster MemoryCache alternative. basically a concurrent dictionary with expiration
1111
/// </summary>
12-
public class FastCache<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
12+
public class FastCache<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>, IDisposable
1313
{
1414
private readonly ConcurrentDictionary<TKey, TtlValue> _dict = new ConcurrentDictionary<TKey, TtlValue>();
1515

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

2626
void _EvictExpired(object state)
2727
{
28-
foreach (var p in _dict)
28+
//overlapped execution? forget it, lets move on
29+
if (Monitor.TryEnter(this))
2930
{
30-
if (p.Value.IsExpired())
31-
_dict.TryRemove(p.Key, out _);
31+
try
32+
{
33+
foreach (var p in _dict)
34+
{
35+
if (p.Value.IsExpired())
36+
_dict.TryRemove(p.Key, out _);
37+
}
38+
}
39+
finally
40+
{
41+
Monitor.Exit(this);
42+
}
3243
}
3344
}
3445
}
@@ -137,7 +148,7 @@ public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory, TimeSpan ttl)
137148
if (TryGet(key, out var value))
138149
return value;
139150

140-
return _dict.GetOrAdd(key, k => new TtlValue(valueFactory(key), ttl)).Value;
151+
return _dict.GetOrAdd(key, (k, v) => new TtlValue(valueFactory(k), v), ttl).Value;
141152
}
142153

143154
/// <summary>
@@ -180,5 +191,19 @@ public bool IsExpired()
180191
return difference > 0;
181192
}
182193
}
194+
195+
//IDispisable members
196+
private bool _disposedValue;
197+
public void Dispose() => Dispose(true);
198+
protected virtual void Dispose(bool disposing)
199+
{
200+
if (!_disposedValue)
201+
{
202+
if (disposing)
203+
_cleanUpTimer.Dispose();
204+
205+
_disposedValue = true;
206+
}
207+
}
183208
}
184209
}

0 commit comments

Comments
 (0)