diff --git a/BitFaster.Caching.UnitTests/SingletonCacheTests.cs b/BitFaster.Caching.UnitTests/SingletonCacheTests.cs index fa233043..2539bbcf 100644 --- a/BitFaster.Caching.UnitTests/SingletonCacheTests.cs +++ b/BitFaster.Caching.UnitTests/SingletonCacheTests.cs @@ -32,6 +32,31 @@ public void AcquireWithSameKeyReturnsSameLifetime() lifetime2.Dispose(); } + [Fact] + public void AcquireWithSameKeyMaintainsReferenceCount() + { + var cache = new SingletonCache(); + + using (var lifetime1 = cache.Acquire("Foo")) + { + using (var lifetime2 = cache.Acquire("Foo")) + { + lifetime1.ReferenceCount.Should().Be(1); + lifetime2.ReferenceCount.Should().Be(2); + } + + using (var lifetime3 = cache.Acquire("Foo")) + { + lifetime3.ReferenceCount.Should().Be(2); + } + } + + using (var lifetime4 = cache.Acquire("Foo")) + { + lifetime4.ReferenceCount.Should().Be(1); + } + } + [Fact] public void AcquireReleaseAcquireReturnsDifferentValue() { diff --git a/BitFaster.Caching/Lifetime.cs b/BitFaster.Caching/Lifetime.cs index f7de345e..74ebf899 100644 --- a/BitFaster.Caching/Lifetime.cs +++ b/BitFaster.Caching/Lifetime.cs @@ -12,6 +12,7 @@ namespace BitFaster.Caching public class Lifetime : IDisposable { private readonly Action onDisposeAction; + private readonly ReferenceCount refCount; private bool isDisposed; /// @@ -19,16 +20,21 @@ public class Lifetime : IDisposable /// /// The value to keep alive. /// The action to perform when the lifetime is terminated. - public Lifetime(T value, Action onDisposeAction) + public Lifetime(ReferenceCount value, Action onDisposeAction) { - this.Value = value; + this.refCount = value; this.onDisposeAction = onDisposeAction; } /// /// Gets the value. /// - public T Value { get; } + public T Value => this.refCount.Value; + + /// + /// Gets the count of Lifetime instances referencing the same value. + /// + public int ReferenceCount => this.refCount.Count; /// /// Terminates the lifetime and performs any cleanup required to release the value. diff --git a/BitFaster.Caching/Scoped.cs b/BitFaster.Caching/Scoped.cs index c6535303..c66f1ca6 100644 --- a/BitFaster.Caching/Scoped.cs +++ b/BitFaster.Caching/Scoped.cs @@ -48,7 +48,7 @@ public Lifetime CreateLifetime() if (oldRefCount == Interlocked.CompareExchange(ref this.refCount, newRefCount, oldRefCount)) { // When Lease is disposed, it calls DecrementReferenceCount - return new Lifetime(oldRefCount.Value, this.DecrementReferenceCount); + return new Lifetime(oldRefCount, this.DecrementReferenceCount); } } } diff --git a/BitFaster.Caching/SingletonCache.cs b/BitFaster.Caching/SingletonCache.cs index c3750b57..531fa2dd 100644 --- a/BitFaster.Caching/SingletonCache.cs +++ b/BitFaster.Caching/SingletonCache.cs @@ -52,7 +52,7 @@ public Lifetime Acquire(TKey key, Func valueFactory) (k) => new ReferenceCount(valueFactory(k)), (_, existingRefCount) => existingRefCount.IncrementCopy()); - return new Lifetime(refCount.Value, () => this.Release(key)); + return new Lifetime(refCount, () => this.Release(key)); } private void Release(TKey key)