Skip to content

Commit 6ef64d2

Browse files
authored
lifetime reference counting (#52)
1 parent 6fd5018 commit 6ef64d2

File tree

4 files changed

+36
-5
lines changed

4 files changed

+36
-5
lines changed

BitFaster.Caching.UnitTests/SingletonCacheTests.cs

+25
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,31 @@ public void AcquireWithSameKeyReturnsSameLifetime()
3232
lifetime2.Dispose();
3333
}
3434

35+
[Fact]
36+
public void AcquireWithSameKeyMaintainsReferenceCount()
37+
{
38+
var cache = new SingletonCache<string, object>();
39+
40+
using (var lifetime1 = cache.Acquire("Foo"))
41+
{
42+
using (var lifetime2 = cache.Acquire("Foo"))
43+
{
44+
lifetime1.ReferenceCount.Should().Be(1);
45+
lifetime2.ReferenceCount.Should().Be(2);
46+
}
47+
48+
using (var lifetime3 = cache.Acquire("Foo"))
49+
{
50+
lifetime3.ReferenceCount.Should().Be(2);
51+
}
52+
}
53+
54+
using (var lifetime4 = cache.Acquire("Foo"))
55+
{
56+
lifetime4.ReferenceCount.Should().Be(1);
57+
}
58+
}
59+
3560
[Fact]
3661
public void AcquireReleaseAcquireReturnsDifferentValue()
3762
{

BitFaster.Caching/Lifetime.cs

+9-3
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,29 @@ namespace BitFaster.Caching
1212
public class Lifetime<T> : IDisposable
1313
{
1414
private readonly Action onDisposeAction;
15+
private readonly ReferenceCount<T> refCount;
1516
private bool isDisposed;
1617

1718
/// <summary>
1819
/// Initializes a new instance of the Lifetime class.
1920
/// </summary>
2021
/// <param name="value">The value to keep alive.</param>
2122
/// <param name="onDisposeAction">The action to perform when the lifetime is terminated.</param>
22-
public Lifetime(T value, Action onDisposeAction)
23+
public Lifetime(ReferenceCount<T> value, Action onDisposeAction)
2324
{
24-
this.Value = value;
25+
this.refCount = value;
2526
this.onDisposeAction = onDisposeAction;
2627
}
2728

2829
/// <summary>
2930
/// Gets the value.
3031
/// </summary>
31-
public T Value { get; }
32+
public T Value => this.refCount.Value;
33+
34+
/// <summary>
35+
/// Gets the count of Lifetime instances referencing the same value.
36+
/// </summary>
37+
public int ReferenceCount => this.refCount.Count;
3238

3339
/// <summary>
3440
/// Terminates the lifetime and performs any cleanup required to release the value.

BitFaster.Caching/Scoped.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public Lifetime<T> CreateLifetime()
4848
if (oldRefCount == Interlocked.CompareExchange(ref this.refCount, newRefCount, oldRefCount))
4949
{
5050
// When Lease is disposed, it calls DecrementReferenceCount
51-
return new Lifetime<T>(oldRefCount.Value, this.DecrementReferenceCount);
51+
return new Lifetime<T>(oldRefCount, this.DecrementReferenceCount);
5252
}
5353
}
5454
}

BitFaster.Caching/SingletonCache.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public Lifetime<TValue> Acquire(TKey key, Func<TKey, TValue> valueFactory)
5252
(k) => new ReferenceCount<TValue>(valueFactory(k)),
5353
(_, existingRefCount) => existingRefCount.IncrementCopy());
5454

55-
return new Lifetime<TValue>(refCount.Value, () => this.Release(key));
55+
return new Lifetime<TValue>(refCount, () => this.Release(key));
5656
}
5757

5858
private void Release(TKey key)

0 commit comments

Comments
 (0)