diff --git a/BitFaster.Caching/SingletonCache.cs b/BitFaster.Caching/SingletonCache.cs
index a4f7bba4..4baeb620 100644
--- a/BitFaster.Caching/SingletonCache.cs
+++ b/BitFaster.Caching/SingletonCache.cs
@@ -7,89 +7,88 @@
namespace BitFaster.Caching
{
- ///
- /// Cache a single value for each key, and maintain in memory only the values that have been acquired
- /// but not yet released.
- ///
- /// The type of the key.
- /// The type of the value.
- public class SingletonCache
- where TValue : new()
- {
- private readonly ConcurrentDictionary> cache;
+ ///
+ /// Cache a single value for each key, and maintain in memory only the values that have been acquired
+ /// but not yet released.
+ ///
+ /// The type of the key.
+ /// The type of the value.
+ public class SingletonCache
+ {
+ private readonly ConcurrentDictionary> cache;
- public SingletonCache()
- {
- this.cache = new ConcurrentDictionary>();
- }
+ public SingletonCache()
+ {
+ this.cache = new ConcurrentDictionary>();
+ }
- public SingletonCache(int concurrencyLevel, int capacity, IEqualityComparer comparer)
- {
- this.cache = new ConcurrentDictionary>(concurrencyLevel, capacity, comparer);
- }
+ public SingletonCache(int concurrencyLevel, int capacity, IEqualityComparer comparer)
+ {
+ this.cache = new ConcurrentDictionary>(concurrencyLevel, capacity, comparer);
+ }
- public Handle Acquire(TKey key)
- {
- var refCount = this.cache.AddOrUpdate(key,
- (_) => new ReferenceCount(new TValue()),
- (_, existingRefCount) => existingRefCount.IncrementCopy());
+ public Handle Acquire(TKey key, Func valueFactory)
+ {
+ var refCount = this.cache.AddOrUpdate(key,
+ (_) => new ReferenceCount(valueFactory(_)),
+ (_, existingRefCount) => existingRefCount.IncrementCopy());
- return new Handle(key, refCount.Value, this);
- }
+ return new Handle(key, refCount.Value, this);
+ }
- private void Release(TKey key)
- {
- while (true)
- {
- var oldRefCount = this.cache[key];
- var newRefCount = oldRefCount.DecrementCopy();
- if (this.cache.TryUpdate(key, newRefCount, oldRefCount))
- {
- if (newRefCount.Count == 0)
- {
- // This will remove from dictionary only if key and the value with ReferenceCount (== 0) matches (under a lock)
- if (((IDictionary>)this.cache).Remove(new KeyValuePair>(key, newRefCount)))
- {
- if (newRefCount.Value is IDisposable d)
- {
- d.Dispose();
- }
- }
- }
- break;
- }
- }
- }
+ private void Release(TKey key)
+ {
+ while (true)
+ {
+ var oldRefCount = this.cache[key];
+ var newRefCount = oldRefCount.DecrementCopy();
+ if (this.cache.TryUpdate(key, newRefCount, oldRefCount))
+ {
+ if (newRefCount.Count == 0)
+ {
+ // This will remove from dictionary only if key and the value with ReferenceCount (== 0) matches (under a lock)
+ if (((IDictionary>)this.cache).Remove(new KeyValuePair>(key, newRefCount)))
+ {
+ if (newRefCount.Value is IDisposable d)
+ {
+ d.Dispose();
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
- public sealed class Handle : IDisposable
- {
- private TKey key;
- private TValue value;
- private SingletonCache cache;
+ public sealed class Handle : IDisposable
+ {
+ private TKey key;
+ private TValue value;
+ private SingletonCache cache;
- public Handle(TKey key, TValue value, SingletonCache cache)
- {
- this.key = key;
- this.value = value;
- this.cache = cache;
- }
+ public Handle(TKey key, TValue value, SingletonCache cache)
+ {
+ this.key = key;
+ this.value = value;
+ this.cache = cache;
+ }
- public TValue Value
- {
- get
- {
- return this.value;
- }
- }
+ public TValue Value
+ {
+ get
+ {
+ return this.value;
+ }
+ }
- public void Dispose()
- {
- if (this.cache != null)
- {
- this.cache.Release(this.key);
- this.cache = null;
- }
- }
- }
- }
+ public void Dispose()
+ {
+ if (this.cache != null)
+ {
+ this.cache.Release(this.key);
+ this.cache = null;
+ }
+ }
+ }
+ }
}
diff --git a/BitFaster.Caching/SingletonCacheExtensions.cs b/BitFaster.Caching/SingletonCacheExtensions.cs
new file mode 100644
index 00000000..7d4ca461
--- /dev/null
+++ b/BitFaster.Caching/SingletonCacheExtensions.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BitFaster.Caching
+{
+ public static class SingletonCacheExtensions
+ {
+ public static SingletonCache.Handle Acquire(this SingletonCache cache, TKey key)
+ where TValue : new()
+ {
+ return cache.Acquire(key, _ => new TValue());
+ }
+ }
+}