@@ -9,7 +9,7 @@ namespace Jitbit.Utils
9
9
/// <summary>
10
10
/// faster MemoryCache alternative. basically a concurrent dictionary with expiration
11
11
/// </summary>
12
- public class FastCache < TKey , TValue > : IEnumerable < KeyValuePair < TKey , TValue > >
12
+ public class FastCache < TKey , TValue > : IEnumerable < KeyValuePair < TKey , TValue > > , IDisposable
13
13
{
14
14
private readonly ConcurrentDictionary < TKey , TtlValue > _dict = new ConcurrentDictionary < TKey , TtlValue > ( ) ;
15
15
@@ -25,10 +25,21 @@ public FastCache(int cleanupJobInterval = 10000)
25
25
26
26
void _EvictExpired ( object state )
27
27
{
28
- foreach ( var p in _dict )
28
+ //overlapped execution? forget it, lets move on
29
+ if ( Monitor . TryEnter ( this ) )
29
30
{
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
+ }
32
43
}
33
44
}
34
45
}
@@ -137,7 +148,7 @@ public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory, TimeSpan ttl)
137
148
if ( TryGet ( key , out var value ) )
138
149
return value ;
139
150
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 ;
141
152
}
142
153
143
154
/// <summary>
@@ -180,5 +191,19 @@ public bool IsExpired()
180
191
return difference > 0 ;
181
192
}
182
193
}
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
+ }
183
208
}
184
209
}
0 commit comments