Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions BitFaster.Caching.UnitTests/Lru/ClassicLruTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ public void WhenComparerIsNullCtorThrows()
constructor.Should().Throw<ArgumentNullException>();
}

[Fact]
public void ConstructAddAndRetrieveWithDefaultCtorReturnsValue()
{
var x = new ConcurrentTLru<int, int>(3);

x.GetOrAdd(1, k => k).Should().Be(1);
}

[Fact]
public void WhenItemIsAddedCountIsCorrect()
{
Expand Down
8 changes: 8 additions & 0 deletions BitFaster.Caching.UnitTests/Lru/ConcurrentLruTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ public void WhenComparerIsNullCtorThrows()
constructor.Should().Throw<ArgumentNullException>();
}

[Fact]
public void ConstructAddAndRetrieveWithDefaultCtorReturnsValue()
{
var x = new ConcurrentLru<int, int>(3);

x.GetOrAdd(1, k => k).Should().Be(1);
}

[Fact]
public void WhenItemIsAddedCountIsCorrect()
{
Expand Down
8 changes: 8 additions & 0 deletions BitFaster.Caching.UnitTests/Lru/ConcurrentTLruTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ public ConcurrentTLruTests()
lru = new ConcurrentTLru<int, string>(1, capacity, EqualityComparer<int>.Default, timeToLive);
}

[Fact]
public void ConstructAddAndRetrieveWithDefaultCtorReturnsValue()
{
var x = new ConcurrentTLru<int, int>(3);

x.GetOrAdd(1, k => k).Should().Be(1);
}

[Fact]
public async Task WhenItemIsExpiredItIsRemoved()
{
Expand Down
8 changes: 8 additions & 0 deletions BitFaster.Caching.UnitTests/Lru/FastConcurrentLruTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,13 @@ public void ConstructAddAndRetrieveWithCustomComparerReturnsValue()
lru.TryGet("FOO", out var value).Should().BeTrue();
value.Should().Be(1);
}

[Fact]
public void ConstructAddAndRetrieveWithDefaultCtorReturnsValue()
{
var x = new FastConcurrentLru<int, int>(3);

x.GetOrAdd(1, k => k).Should().Be(1);
}
}
}
8 changes: 8 additions & 0 deletions BitFaster.Caching.UnitTests/Lru/FastConcurrentTLruTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,13 @@ public void ConstructAddAndRetrieveWithCustomComparerReturnsValue()
lru.TryGet("FOO", out var value).Should().BeTrue();
value.Should().Be(1);
}

[Fact]
public void ConstructAddAndRetrieveWithDefaultCtorReturnsValue()
{
var x = new FastConcurrentTLru<int, int>(3);

x.GetOrAdd(1, k => k).Should().Be(1);
}
}
}
5 changes: 5 additions & 0 deletions BitFaster.Caching/Lru/ClassicLru.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ public sealed class ClassicLru<K, V> : ICache<K, V>
private long requestHitCount;
private long requestTotalCount;

public ClassicLru(int capacity)
: this(Defaults.ConcurrencyLevel, capacity, EqualityComparer<K>.Default)
{
}

public ClassicLru(int concurrencyLevel, int capacity, IEqualityComparer<K> comparer)
{
if (capacity < 3)
Expand Down
5 changes: 5 additions & 0 deletions BitFaster.Caching/Lru/ConcurrentLru.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ namespace BitFaster.Caching.Lru
{
public sealed class ConcurrentLru<K, V> : TemplateConcurrentLru<K, V, LruItem<K, V>, LruPolicy<K, V>, HitCounter>
{
public ConcurrentLru(int capacity)
: base(Defaults.ConcurrencyLevel, capacity, EqualityComparer<K>.Default, new LruPolicy<K, V>(), new HitCounter())
{
}

public ConcurrentLru(int concurrencyLevel, int capacity, IEqualityComparer<K> comparer)
: base(concurrencyLevel, capacity, comparer, new LruPolicy<K, V>(), new HitCounter())
{
Expand Down
5 changes: 5 additions & 0 deletions BitFaster.Caching/Lru/ConcurrentTLru.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ namespace BitFaster.Caching.Lru
{
public sealed class ConcurrentTLru<K, V> : TemplateConcurrentLru<K, V, TimeStampedLruItem<K, V>, TLruDateTimePolicy<K, V>, HitCounter>
{
public ConcurrentTLru(int capacity)
: base(Defaults.ConcurrencyLevel, capacity, EqualityComparer<K>.Default, new TLruDateTimePolicy<K, V>(), new HitCounter())
{
}

public ConcurrentTLru(int concurrencyLevel, int capacity, IEqualityComparer<K> comparer, TimeSpan timeToLive)
: base(concurrencyLevel, capacity, comparer, new TLruDateTimePolicy<K, V>(timeToLive), new HitCounter())
{
Expand Down
14 changes: 14 additions & 0 deletions BitFaster.Caching/Lru/Defaults.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace BitFaster.Caching.Lru
{
internal static class Defaults
{
public static int ConcurrencyLevel
{
get { return Environment.ProcessorCount; }
}
}
}
5 changes: 5 additions & 0 deletions BitFaster.Caching/Lru/FastConcurrentLru.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ namespace BitFaster.Caching.Lru
{
public sealed class FastConcurrentLru<K, V> : TemplateConcurrentLru<K, V, LruItem<K, V>, LruPolicy<K, V>, NullHitCounter>
{
public FastConcurrentLru(int capacity)
: base(Defaults.ConcurrencyLevel, capacity, EqualityComparer<K>.Default, new LruPolicy<K, V>(), new NullHitCounter())
{
}

public FastConcurrentLru(int concurrencyLevel, int capacity, IEqualityComparer<K> comparer)
: base(concurrencyLevel, capacity, comparer, new LruPolicy<K, V>(), new NullHitCounter())
{
Expand Down
5 changes: 5 additions & 0 deletions BitFaster.Caching/Lru/FastConcurrentTLru.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ namespace BitFaster.Caching.Lru
{
public sealed class FastConcurrentTLru<K, V> : TemplateConcurrentLru<K, V, TickCountLruItem<K, V>, TLruTicksPolicy<K, V>, NullHitCounter>
{
public FastConcurrentTLru(int capacity)
: base(Defaults.ConcurrencyLevel, capacity, EqualityComparer<K>.Default, new TLruTicksPolicy<K, V>(), new NullHitCounter())
{
}

public FastConcurrentTLru(int concurrencyLevel, int capacity, IEqualityComparer<K> comparer, TimeSpan timeToLive)
: base(concurrencyLevel, capacity, comparer, new TLruTicksPolicy<K, V>(timeToLive), new NullHitCounter())
{
Expand Down
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ High performance, thread-safe in-memory caching primitives for .NET.
`ConcurrentLru` and `ConcurrentTLru` are intended as a drop in replacement for `ConcurrentDictionary`, and a much faster alternative to the `System.Runtime.Caching.MemoryCache` family of classes (e.g. `HttpRuntime.Cache`, `System.Web.Caching` etc).

```csharp
int concurrency = 4;
int capacity = 666;
var lru = new ConcurrentLru<int, SomeItem>(concurrency, capacity, EqualityComparer<int>.Default);
var lru = new ConcurrentLru<int, SomeItem>(capacity);

var value = lru.GetOrAdd(1, (k) => new SomeItem(k));
var value = await lru.GetOrAddAsync(0, (k) => Task.FromResult(new SomeItem(k)));
Expand All @@ -39,9 +38,8 @@ All cache classes in BitFaster.Caching own the lifetime of cached values, and wi
To avoid races using objects after they have been disposed by the cache, wrap them with `Scoped`. The call to `CreateLifetime` creates a `Lifetime` that guarantees the scoped object will not be disposed until the lifetime is disposed. `Scoped` is thread safe, and guarantees correct disposal for concurrent lifetimes.

```csharp
int concurrency = 4;
int capacity = 666;
var lru = new ConcurrentLru<int, Scoped<SomeDisposable>>(concurrency, capacity, EqualityComparer<int>.Default);
var lru = new ConcurrentLru<int, Scoped<SomeDisposable>>(capacity);
var valueFactory = new SomeDisposableValueFactory();

using (var lifetime = lru.GetOrAdd(1, valueFactory.Create).CreateLifetime())
Expand Down