Skip to content

Commit

Permalink
GetOrAdd overload with factory argument that prevents allocations
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-jitbit committed May 4, 2024
1 parent 2a016db commit d5d937a
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 1 deletion.
25 changes: 24 additions & 1 deletion FastCache/FastCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,30 @@ public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory, TimeSpan ttl)
if (TryGet(key, out var value))
return value;

return _dict.GetOrAdd(key, (k, v) => new TtlValue(v.valueFactory(k), v.ttl), (ttl, valueFactory)).Value;
return _dict.GetOrAdd(
key,
(k, arg) => new TtlValue(arg.valueFactory(k), arg.ttl),
(ttl, valueFactory)
).Value;
}

/// <summary>
/// Adds a key/value pair by using the specified function if the key does not already exist, or returns the existing value if the key exists.
/// </summary>
/// <param name="key">The key to add</param>
/// <param name="valueFactory">The factory function used to generate the item for the key</param>
/// <param name="ttl">TTL of the item</param>
/// <param name="factoryArgument">Argument value to pass into valueFactory</param>
public TValue GetOrAdd<TArg>(TKey key, Func<TKey, TArg, TValue> valueFactory, TimeSpan ttl, TArg factoryArgument)
{
if (TryGet(key, out var value))
return value;

return _dict.GetOrAdd(
key,
(k, arg) => new TtlValue(arg.valueFactory(k, arg.factoryArgument), arg.ttl),
(ttl, valueFactory, factoryArgument)
).Value;
}

/// <summary>
Expand Down
12 changes: 12 additions & 0 deletions UnitTests/UnitTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,18 @@ public async Task TestGetOrAdd()
Assert.IsFalse(cache.TryGet("key", out _));
}

[TestMethod]
public async Task TestGetOrAddWithArg()
{
var cache = new FastCache<string, int>();
cache.GetOrAdd("key", (k, arg) => 1024 + arg.Length, TimeSpan.FromMilliseconds(100), "test123");
Assert.IsTrue(cache.TryGet("key", out int res) && res == 1031);

//eviction
await Task.Delay(110);
Assert.IsFalse(cache.TryGet("key", out _));
}

[TestMethod]
public void TestClear()
{
Expand Down

0 comments on commit d5d937a

Please sign in to comment.