-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
IDisposable, no closure in GetOrAdd, Evicter debounce, fixes #1
- Loading branch information
1 parent
6749a7e
commit ebef51e
Showing
2 changed files
with
39 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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>(); | ||
|
||
|
@@ -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.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
alex-jitbit
Author
Member
|
||
{ | ||
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); | ||
} | ||
} | ||
} | ||
} | ||
|
@@ -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> | ||
|
@@ -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; | ||
} | ||
} | ||
} | ||
} |
Take a look at this: Why is lock(this) {...} bad? It applies to all
Monitor
methods as well, since thelock
is based onMonitor
.