Skip to content

Commit e3cddc7

Browse files
authored
Extract ConcurrentLfuCore with generic node and policy (#520)
1 parent fc969c8 commit e3cddc7

File tree

6 files changed

+335
-161
lines changed

6 files changed

+335
-161
lines changed

BitFaster.Caching.UnitTests/Lfu/ConcurrentLfuSoakTests.cs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -307,32 +307,33 @@ private async Task RunIntegrityCheckAsync(ConcurrentLfu<int, string> lfu, int it
307307
RunIntegrityCheck(lfu, this.output);
308308
}
309309

310-
311310
private static void RunIntegrityCheck<K,V>(ConcurrentLfu<K,V> cache, ITestOutputHelper output)
312311
{
313-
new ConcurrentLfuIntegrityChecker<K, V>(cache).Validate(output);
312+
new ConcurrentLfuIntegrityChecker<K, V, AccessOrderNode<K, V>, AccessOrderPolicy<K, V>>(cache.Core).Validate(output);
314313
}
315314
}
316315

317-
public class ConcurrentLfuIntegrityChecker<K, V>
316+
internal class ConcurrentLfuIntegrityChecker<K, V, N, P>
317+
where N : LfuNode<K, V>
318+
where P : struct, INodePolicy<K, V, N>
318319
{
319-
private readonly ConcurrentLfu<K, V> cache;
320+
private readonly ConcurrentLfuCore<K, V, N, P> cache;
320321

321322
private readonly LfuNodeList<K, V> windowLru;
322323
private readonly LfuNodeList<K, V> probationLru;
323324
private readonly LfuNodeList<K, V> protectedLru;
324325

325-
private readonly StripedMpscBuffer<LfuNode<K, V>> readBuffer;
326-
private readonly MpscBoundedBuffer<LfuNode<K, V>> writeBuffer;
326+
private readonly StripedMpscBuffer<N> readBuffer;
327+
private readonly MpscBoundedBuffer<N> writeBuffer;
327328

328-
private static FieldInfo windowLruField = typeof(ConcurrentLfu<K, V>).GetField("windowLru", BindingFlags.NonPublic | BindingFlags.Instance);
329-
private static FieldInfo probationLruField = typeof(ConcurrentLfu<K, V>).GetField("probationLru", BindingFlags.NonPublic | BindingFlags.Instance);
330-
private static FieldInfo protectedLruField = typeof(ConcurrentLfu<K, V>).GetField("protectedLru", BindingFlags.NonPublic | BindingFlags.Instance);
329+
private static FieldInfo windowLruField = typeof(ConcurrentLfuCore<K, V, N, P>).GetField("windowLru", BindingFlags.NonPublic | BindingFlags.Instance);
330+
private static FieldInfo probationLruField = typeof(ConcurrentLfuCore<K, V, N, P>).GetField("probationLru", BindingFlags.NonPublic | BindingFlags.Instance);
331+
private static FieldInfo protectedLruField = typeof(ConcurrentLfuCore<K, V, N, P>).GetField("protectedLru", BindingFlags.NonPublic | BindingFlags.Instance);
331332

332-
private static FieldInfo readBufferField = typeof(ConcurrentLfu<K, V>).GetField("readBuffer", BindingFlags.NonPublic | BindingFlags.Instance);
333-
private static FieldInfo writeBufferField = typeof(ConcurrentLfu<K, V>).GetField("writeBuffer", BindingFlags.NonPublic | BindingFlags.Instance);
333+
private static FieldInfo readBufferField = typeof(ConcurrentLfuCore<K, V, N, P>).GetField("readBuffer", BindingFlags.NonPublic | BindingFlags.Instance);
334+
private static FieldInfo writeBufferField = typeof(ConcurrentLfuCore<K, V, N, P>).GetField("writeBuffer", BindingFlags.NonPublic | BindingFlags.Instance);
334335

335-
public ConcurrentLfuIntegrityChecker(ConcurrentLfu<K, V> cache)
336+
public ConcurrentLfuIntegrityChecker(ConcurrentLfuCore<K, V, N, P> cache)
336337
{
337338
this.cache = cache;
338339

@@ -341,8 +342,8 @@ public ConcurrentLfuIntegrityChecker(ConcurrentLfu<K, V> cache)
341342
this.probationLru = (LfuNodeList<K, V>)probationLruField.GetValue(cache);
342343
this.protectedLru = (LfuNodeList<K, V>)protectedLruField.GetValue(cache);
343344

344-
this.readBuffer = (StripedMpscBuffer<LfuNode<K, V>>)readBufferField.GetValue(cache);
345-
this.writeBuffer = (MpscBoundedBuffer<LfuNode<K, V>>)writeBufferField.GetValue(cache);
345+
this.readBuffer = (StripedMpscBuffer<N>)readBufferField.GetValue(cache);
346+
this.writeBuffer = (MpscBoundedBuffer<N>)writeBufferField.GetValue(cache);
346347
}
347348

348349
public void Validate(ITestOutputHelper output)

BitFaster.Caching.UnitTests/Lfu/ConcurrentLfuTests.cs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,30 @@ public ConcurrentLfuTests(ITestOutputHelper output)
2626
this.output = output;
2727
}
2828

29+
[Fact]
30+
public void WhenCapacityIsLessThan3CtorThrows()
31+
{
32+
Action constructor = () => { var x = new ConcurrentLfu<int, string>(2); };
33+
34+
constructor.Should().Throw<ArgumentOutOfRangeException>();
35+
}
36+
37+
[Fact]
38+
public void WhenCapacityIsValidCacheIsCreated()
39+
{
40+
var x = new ConcurrentLfu<int, string>(3);
41+
42+
x.Capacity.Should().Be(3);
43+
}
44+
45+
[Fact]
46+
public void WhenConcurrencyIsLessThan1CtorThrows()
47+
{
48+
Action constructor = () => { var x = new ConcurrentLfu<int, string>(0, 20, new ForegroundScheduler(), EqualityComparer<int>.Default); };
49+
50+
constructor.Should().Throw<ArgumentOutOfRangeException>();
51+
}
52+
2953
[Fact]
3054
public void DefaultSchedulerIsThreadPool()
3155
{
@@ -548,7 +572,11 @@ public void WhenItemsAddedGenericEnumerateContainsKvps()
548572
cache.GetOrAdd(1, k => k + 1);
549573
cache.GetOrAdd(2, k => k + 1);
550574

551-
cache.Should().BeEquivalentTo(new[] { new KeyValuePair<int, int>(1, 2), new KeyValuePair<int, int>(2, 3) });
575+
var enumerator = cache.GetEnumerator();
576+
enumerator.MoveNext().Should().BeTrue();
577+
enumerator.Current.Should().Be(new KeyValuePair<int, int>(1, 2));
578+
enumerator.MoveNext().Should().BeTrue();
579+
enumerator.Current.Should().Be(new KeyValuePair<int, int>(2, 3));
552580
}
553581

554582
[Fact]

BitFaster.Caching/BitFaster.Caching.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFrameworks>netstandard2.0;netcoreapp3.1;net6.0</TargetFrameworks>
5-
<LangVersion>9.0</LangVersion>
5+
<LangVersion>10.0</LangVersion>
66
<Authors>Alex Peck</Authors>
77
<Company />
88
<Product>BitFaster.Caching</Product>

0 commit comments

Comments
 (0)