Skip to content

Commit 434a7be

Browse files
authored
Add new interface to expose 3 new methods without breaking existing clients (#566)
* Add ICache2 and implement it in ConcurrentLruCore to expose 3 new methods without breaking existing clients * a * a * Rename ICache2 to ICacheExt * Rename File * Add comment ---------
1 parent 7f4df79 commit 434a7be

File tree

5 files changed

+101
-3
lines changed

5 files changed

+101
-3
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
using System;
2+
using System.Linq;
3+
using BitFaster.Caching.Lfu;
4+
using BitFaster.Caching.Lru;
5+
using FluentAssertions;
6+
using Xunit;
7+
8+
namespace BitFaster.Caching.UnitTests.Lru
9+
{
10+
public class CacheExtTests
11+
{
12+
[Fact]
13+
public void CanUseICache2FromClassicLru()
14+
{
15+
var cache = new ClassicLru<int, string>(5);
16+
var cache2 = (ICacheExt<int, string>)cache;
17+
cache2.GetOrAdd(42, static (k, i) => (k + i).ToString(), 1).Should().Be("43");
18+
cache2.TryRemove(43, out _).Should().BeFalse();
19+
var first = cache2.First();
20+
cache2.TryRemove(first).Should().BeTrue();
21+
}
22+
23+
[Fact]
24+
public void CanUseICache2FromConcurrentLfuBuilder()
25+
{
26+
var cache = new ConcurrentLfuBuilder<int, string>()
27+
.WithCapacity(5)
28+
.Build();
29+
30+
var cache2 = (ICacheExt<int, string>)cache;
31+
cache2.GetOrAdd(42, static (k, i) => (k + i).ToString(), 1).Should().Be("43");
32+
cache2.TryRemove(43, out _).Should().BeFalse();
33+
var first = cache2.First();
34+
cache2.TryRemove(first).Should().BeTrue();
35+
}
36+
37+
[Fact]
38+
public void CanUseICache2FromConcurrentLruBuilder()
39+
{
40+
var cache = new ConcurrentLruBuilder<int, string>()
41+
.WithCapacity(5)
42+
.WithExpireAfterAccess(TimeSpan.FromSeconds(5))
43+
.Build();
44+
45+
var cache2 = (ICacheExt<int, string>)cache;
46+
cache2.GetOrAdd(42, static (k, i) => (k + i).ToString(), 1).Should().Be("43");
47+
cache2.TryRemove(43, out _).Should().BeFalse();
48+
var first = cache2.First();
49+
cache2.TryRemove(first).Should().BeTrue();
50+
}
51+
}
52+
}

BitFaster.Caching/ICacheExt.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics.CodeAnalysis;
4+
5+
namespace BitFaster.Caching
6+
{
7+
/// <summary>
8+
/// Represents a generic cache of key/value pairs. This is a new interface with new methods to avoid breaking backward compatibility.
9+
/// </summary>
10+
/// <typeparam name="K">The type of keys in the cache.</typeparam>
11+
/// <typeparam name="V">The type of values in the cache.</typeparam>
12+
public interface ICacheExt<K, V> : ICache<K, V>
13+
{
14+
// Following methods were also defined in ICache with default interface implementation which only works for
15+
// certain build targets, for other build targets we will define them within this new interface to avoid breaking
16+
// existing clients.
17+
#if !NETCOREAPP3_0_OR_GREATER
18+
/// <summary>
19+
/// Adds a key/value pair to the cache if the key does not already exist. Returns the new value, or the
20+
/// existing value if the key already exists.
21+
/// </summary>
22+
/// <typeparam name="TArg">The type of an argument to pass into valueFactory.</typeparam>
23+
/// <param name="key">The key of the element to add.</param>
24+
/// <param name="valueFactory">The factory function used to generate a value for the key.</param>
25+
/// <param name="factoryArgument">An argument value to pass into valueFactory.</param>
26+
/// <returns>The value for the key. This will be either the existing value for the key if the key is already
27+
/// in the cache, or the new value if the key was not in the cache.</returns>
28+
V GetOrAdd<TArg>(K key, Func<K, TArg, V> valueFactory, TArg factoryArgument);
29+
30+
/// <summary>
31+
/// Attempts to remove and return the value that has the specified key.
32+
/// </summary>
33+
/// <param name="key">The key of the element to remove.</param>
34+
/// <param name="value">When this method returns, contains the object removed, or the default value of the value type if key does not exist.</param>
35+
/// <returns>true if the object was removed successfully; otherwise, false.</returns>
36+
bool TryRemove(K key, [MaybeNullWhen(false)] out V value);
37+
38+
/// <summary>
39+
/// Attempts to remove the specified key value pair.
40+
/// </summary>
41+
/// <param name="item">The item to remove.</param>
42+
/// <returns>true if the item was removed successfully; otherwise, false.</returns>
43+
bool TryRemove(KeyValuePair<K, V> item);
44+
#endif
45+
}
46+
}

BitFaster.Caching/Lfu/ConcurrentLfu.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ namespace BitFaster.Caching.Lfu
3232
/// https://github.com/ben-manes/caffeine
3333
[DebuggerTypeProxy(typeof(ConcurrentLfu<,>.LfuDebugView<>))]
3434
[DebuggerDisplay("Count = {Count}/{Capacity}")]
35-
public sealed class ConcurrentLfu<K, V> : ICache<K, V>, IAsyncCache<K, V>, IBoundedPolicy
35+
public sealed class ConcurrentLfu<K, V> : ICacheExt<K, V>, IAsyncCache<K, V>, IBoundedPolicy
3636
where K : notnull
3737
{
3838
// Note: for performance reasons this is a mutable struct, it cannot be readonly.

BitFaster.Caching/Lru/ClassicLru.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ namespace BitFaster.Caching.Lru
1818
/// </remarks>
1919
/// <typeparam name="K">The type of the key</typeparam>
2020
/// <typeparam name="V">The type of the value</typeparam>
21-
public sealed class ClassicLru<K, V> : ICache<K, V>, IAsyncCache<K, V>, IBoundedPolicy, IEnumerable<KeyValuePair<K, V>>
21+
public sealed class ClassicLru<K, V> : ICacheExt<K, V>, IAsyncCache<K, V>, IBoundedPolicy, IEnumerable<KeyValuePair<K, V>>
2222
where K : notnull
2323
{
2424
private readonly int capacity;

BitFaster.Caching/Lru/ConcurrentLruCore.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ namespace BitFaster.Caching.Lru
3232
/// <item><description>When cold is full, cold tail is moved to warm head or removed from dictionary on depending on WasAccessed.</description></item>
3333
///</list>
3434
/// </remarks>
35-
public class ConcurrentLruCore<K, V, I, P, T> : ICache<K, V>, IAsyncCache<K, V>, IEnumerable<KeyValuePair<K, V>>
35+
public class ConcurrentLruCore<K, V, I, P, T> : ICacheExt<K, V>, IAsyncCache<K, V>, IEnumerable<KeyValuePair<K, V>>
3636
where K : notnull
3737
where I : LruItem<K, V>
3838
where P : struct, IItemPolicy<K, V, I>

0 commit comments

Comments
 (0)