@@ -210,6 +210,54 @@ await Threaded.Run(4, () =>
210210
211211 cache . Metrics . Value . Evicted . Should ( ) . Be ( 0 ) ;
212212 }
213+
214+ [ Theory ]
215+ [ Repeat ( 10 ) ]
216+ public async Task WhenConcurrentGetAndClearCacheEndsInConsistentState ( int iteration )
217+ {
218+ await Threaded . Run ( 4 , r => {
219+ for ( int i = 0 ; i < 100000 ; i ++ )
220+ {
221+ // clear 6,250 times per 1_000_000 iters
222+ if ( r == 0 && ( i & 15 ) == 15 )
223+ {
224+ lru . Clear ( ) ;
225+ }
226+
227+ lru . GetOrAdd ( i + 1 , i => i . ToString ( ) ) ;
228+ }
229+ } ) ;
230+
231+ this . testOutputHelper . WriteLine ( $ "{ iteration } { lru . HotCount } { lru . WarmCount } { lru . ColdCount } ") ;
232+ this . testOutputHelper . WriteLine ( string . Join ( " " , lru . Keys ) ) ;
233+
234+ RunIntegrityCheck ( ) ;
235+ }
236+
237+ [ Theory ]
238+ [ Repeat ( 10 ) ]
239+ public async Task WhenConcurrentGetAndClearDuringWarmupCacheEndsInConsistentState ( int iteration )
240+ {
241+ await Threaded . Run ( 4 , r => {
242+ for ( int i = 0 ; i < 100000 ; i ++ )
243+ {
244+ // clear 25,000 times per 1_000_000 iters
245+ // capacity is 9, so we will try to clear before warmup is done
246+ if ( r == 0 && ( i & 3 ) == 3 )
247+ {
248+ lru . Clear ( ) ;
249+ }
250+
251+ lru . GetOrAdd ( i + 1 , i => i . ToString ( ) ) ;
252+ }
253+ } ) ;
254+
255+ this . testOutputHelper . WriteLine ( $ "{ iteration } { lru . HotCount } { lru . WarmCount } { lru . ColdCount } ") ;
256+ this . testOutputHelper . WriteLine ( string . Join ( " " , lru . Keys ) ) ;
257+
258+ RunIntegrityCheck ( ) ;
259+ }
260+
213261 private void RunIntegrityCheck ( )
214262 {
215263 new ConcurrentLruIntegrityChecker < int , string , LruItem < int , string > , LruPolicy < int , string > , TelemetryPolicy < int , string > > ( this . lru ) . Validate ( ) ;
0 commit comments