Skip to content

Commit 1a7cdc6

Browse files
committed
Release 5.21.0
1 parent 060ecd6 commit 1a7cdc6

File tree

30 files changed

+534
-184
lines changed

30 files changed

+534
-184
lines changed

CHANGELOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,28 @@
11
Release Notes
22
====
33

4+
# 04-08-2025
5+
<a href="https://www.nuget.org/packages/dotnext/5.21.0">DotNext 5.21.0</a>
6+
* Added `Disposable.CreateException()` protected method
7+
8+
<a href="https://www.nuget.org/packages/dotnext.metaprogramming/5.21.0">DotNext.Metaprogramming 5.21.0</a>
9+
* Updated dependencies
10+
11+
<a href="https://www.nuget.org/packages/dotnext.unsafe/5.21.0">DotNext.Unsafe 5.21.0</a>
12+
* Updated dependencies
13+
14+
<a href="https://www.nuget.org/packages/dotnext.threading/5.21.0">DotNext.Threading 5.21.0</a>
15+
* Added `Contains`, `ReplaceAsync` methods to `RandomAccessCache<TKey, TValue>` class as well as scanning enumerator
16+
17+
<a href="https://www.nuget.org/packages/dotnext.io/5.21.0">DotNext.IO 5.21.0</a>
18+
* Updated dependencies
19+
20+
<a href="https://www.nuget.org/packages/dotnext.net.cluster/5.21.0">DotNext.Net.Cluster 5.21.0</a>
21+
* Updated dependencies
22+
23+
<a href="https://www.nuget.org/packages/dotnext.aspnetcore.cluster/5.21.0">DotNext.AspNetCore.Cluster 5.21.0</a>
24+
* Updated dependencies
25+
426
# 03-30-2025
527
<a href="https://www.nuget.org/packages/dotnext/5.20.0">DotNext 5.20.0</a>
628
* Introduced `List.Repeat()` static method to construct read-only lists of repeatable items. Similar to [Enumerable.Repeat](https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.repeat) but returns [IReadOnlyList&lt;T&gt;](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.ireadonlylist-1)

README.md

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,29 +44,27 @@ All these things are implemented in 100% managed code on top of existing .NET AP
4444
* [NuGet Packages](https://www.nuget.org/profiles/rvsakno)
4545

4646
# What's new
47-
Release Date: 03-30-2025
47+
Release Date: 04-08-2025
4848

49-
<a href="https://www.nuget.org/packages/dotnext/5.20.0">DotNext 5.20.0</a>
50-
* Introduced `List.Repeat()` static method to construct read-only lists of repeatable items. Similar to [Enumerable.Repeat](https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.repeat) but returns [IReadOnlyList&lt;T&gt;](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.ireadonlylist-1)
51-
* Added `Number.RoundUp` and `Number.RoundDown` generic extension methods to round the numbers to the multiple of the specified value
49+
<a href="https://www.nuget.org/packages/dotnext/5.21.0">DotNext 5.21.0</a>
50+
* Added `Disposable.CreateException()` protected method
5251

53-
<a href="https://www.nuget.org/packages/dotnext.metaprogramming/5.20.0">DotNext.Metaprogramming 5.20.0</a>
52+
<a href="https://www.nuget.org/packages/dotnext.metaprogramming/5.21.0">DotNext.Metaprogramming 5.21.0</a>
5453
* Updated dependencies
5554

56-
<a href="https://www.nuget.org/packages/dotnext.unsafe/5.20.0">DotNext.Unsafe 5.20.0</a>
57-
* Added static methods to `UnmanagedMemory` for page-aligned memory allocation
55+
<a href="https://www.nuget.org/packages/dotnext.unsafe/5.21.0">DotNext.Unsafe 5.21.0</a>
56+
* Updated dependencies
5857

59-
<a href="https://www.nuget.org/packages/dotnext.threading/5.20.0">DotNext.Threading 5.20.0</a>
60-
* Improved debugging experience of `RandomAccessCache<TKey, TValue>` class
61-
* Added `AsyncCounter.TryIncrement` method that allows to specify the upper bound of the counter. As a result, `AsyncCounter` class can be used as a rate limiter
58+
<a href="https://www.nuget.org/packages/dotnext.threading/5.21.0">DotNext.Threading 5.21.0</a>
59+
* Added `Contains`, `ReplaceAsync` methods to `RandomAccessCache<TKey, TValue>` class as well as scanning enumerator
6260

63-
<a href="https://www.nuget.org/packages/dotnext.io/5.20.0">DotNext.IO 5.20.0</a>
64-
* Introduced `DiskSpacePool` class to assist with building caches when the cached data stored on the disk rather than in memory. The class can be combined with `RandomAccessCache<TKey, TValue>` to organize L1 application-specific caches (while L0 resides in memory and can be organized on top of `RandomAccessCache<TKey, TValue>` as well)
61+
<a href="https://www.nuget.org/packages/dotnext.io/5.21.0">DotNext.IO 5.21.0</a>
62+
* Updated dependencies
6563

66-
<a href="https://www.nuget.org/packages/dotnext.net.cluster/5.20.0">DotNext.Net.Cluster 5.20.0</a>
64+
<a href="https://www.nuget.org/packages/dotnext.net.cluster/5.21.0">DotNext.Net.Cluster 5.21.0</a>
6765
* Updated dependencies
6866

69-
<a href="https://www.nuget.org/packages/dotnext.aspnetcore.cluster/5.20.0">DotNext.AspNetCore.Cluster 5.20.0</a>
67+
<a href="https://www.nuget.org/packages/dotnext.aspnetcore.cluster/5.21.0">DotNext.AspNetCore.Cluster 5.21.0</a>
7068
* Updated dependencies
7169

7270
Changelog for previous versions located [here](./CHANGELOG.md).

src/Directory.Packages.props

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,28 @@
1919
</ItemGroup>
2020
<ItemGroup>
2121
<!--Microsoft packages-->
22-
<PackageVersion Include="Microsoft.AspNetCore.Connections.Abstractions" Version="8.0.12" />
23-
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.2" />
22+
<PackageVersion Include="Microsoft.AspNetCore.Connections.Abstractions" Version="8.0.14" />
23+
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.3" />
2424
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" />
2525
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="8.0.1" />
2626
<PackageVersion Include="Microsoft.Extensions.Http" Version="8.0.1" />
2727
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
2828
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" />
2929
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
30-
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
31-
<PackageVersion Include="MSTest.Engine" Version="1.0.0-alpha.24562.1" />
32-
<PackageVersion Include="MSTest.SourceGeneration" Version="1.0.0-alpha.24562.1" />
33-
<PackageVersion Include="Microsoft.Testing.Extensions.TrxReport" Version="1.0.2" />
34-
<PackageVersion Include="Microsoft.Testing.Platform.MSBuild" Version="1.5.1" />
35-
<PackageVersion Include="MSTest.TestFramework" Version="3.7.1" />
36-
<PackageVersion Include="MSTest.Analyzers" Version="3.7.1" />
30+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
31+
<PackageVersion Include="MSTest.Engine" Version="1.0.0-alpha.25167.10" />
32+
<PackageVersion Include="MSTest.SourceGeneration" Version="1.0.0-alpha.25167.10" />
33+
<PackageVersion Include="Microsoft.Testing.Extensions.TrxReport" Version="1.6.3" />
34+
<PackageVersion Include="Microsoft.Testing.Platform.MSBuild" Version="1.6.3" />
35+
<PackageVersion Include="MSTest.TestFramework" Version="3.8.3" />
36+
<PackageVersion Include="MSTest.Analyzers" Version="3.8.3" />
3737
</ItemGroup>
3838
<ItemGroup>
3939
<!--Misc packages-->
4040
<PackageVersion Include="BenchmarkDotNet" Version="0.14.0" />
4141
<PackageVersion Include="FastMember.Signed" Version="1.5.0" />
4242
<PackageVersion Include="xunit" Version="2.9.3" />
43-
<PackageVersion Include="xunit.runner.visualstudio" Version="3.0.1"/>
43+
<PackageVersion Include="xunit.runner.visualstudio" Version="3.0.2"/>
4444
<PackageVersion Include="coverlet.collector" Version="6.0.4"/>
4545
</ItemGroup>
4646
</Project>

src/DotNext.IO/DotNext.IO.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<Authors>.NET Foundation and Contributors</Authors>
1212
<Company />
1313
<Product>.NEXT Family of Libraries</Product>
14-
<VersionPrefix>5.20.0</VersionPrefix>
14+
<VersionPrefix>5.21.0</VersionPrefix>
1515
<VersionSuffix></VersionSuffix>
1616
<AssemblyName>DotNext.IO</AssemblyName>
1717
<PackageLicenseExpression>MIT</PackageLicenseExpression>

src/DotNext.Metaprogramming/DotNext.Metaprogramming.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<ImplicitUsings>true</ImplicitUsings>
99
<IsAotCompatible>false</IsAotCompatible>
1010
<Features>nullablePublicOnly</Features>
11-
<VersionPrefix>5.20.0</VersionPrefix>
11+
<VersionPrefix>5.21.0</VersionPrefix>
1212
<VersionSuffix></VersionSuffix>
1313
<Authors>.NET Foundation</Authors>
1414
<Product>.NEXT Family of Libraries</Product>

src/DotNext.Metaprogramming/Metaprogramming/LambdaContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ namespace DotNext.Metaprogramming;
1616

1717
internal LambdaContext(LambdaExpression lambda) => this.lambda = new WeakReference(lambda);
1818

19-
private LambdaExpression Lambda => lambda?.Target is LambdaExpression result ? result : throw new ObjectDisposedException(nameof(LambdaContext));
19+
private LambdaExpression Lambda => lambda?.Target as LambdaExpression ?? throw new ObjectDisposedException(nameof(LambdaContext));
2020

2121
/// <summary>
2222
/// Gets parameter of the lambda function.

src/DotNext.Metaprogramming/Metaprogramming/LoopContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace DotNext.Metaprogramming;
1717

1818
internal LoopContext(ILoopLabels loop) => this.loop = new WeakReference(loop);
1919

20-
private ILoopLabels Labels => loop?.Target is ILoopLabels result ? result : throw new ObjectDisposedException(nameof(LoopContext));
20+
private ILoopLabels Labels => loop?.Target as ILoopLabels ?? throw new ObjectDisposedException(nameof(LoopContext));
2121

2222
internal LabelTarget ContinueLabel => Labels.ContinueLabel;
2323

src/DotNext.Metaprogramming/Runtime/CompilerServices/AsyncStateMachineBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ internal MemberExpression Build(Type stateType)
546546
}
547547
}
548548

549-
private static MemberExpression[] CreateStateHolderType(Type returnType, bool usePooling, IReadOnlyList<ParameterExpression> variables, out ParameterExpression stateMachine)
549+
private static MemberExpression[] CreateStateHolderType(Type returnType, bool usePooling, ReadOnlySpan<ParameterExpression> variables, out ParameterExpression stateMachine)
550550
{
551551
var sm = new StateMachineBuilder(returnType, usePooling);
552552
MemberExpression[] slots;

src/DotNext.Tests/DotNext.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<LangVersion>latest</LangVersion>
77
<ImplicitUsings>true</ImplicitUsings>
88
<EnableNETAnalyzers>false</EnableNETAnalyzers>
9-
<Version>5.20.0</Version>
9+
<Version>5.21.0</Version>
1010
<IsPackable>false</IsPackable>
1111
<Authors>.NET Foundation and Contributors</Authors>
1212
<Product>.NEXT Family of Libraries</Product>

src/DotNext.Tests/Runtime/Caching/RandomAccessCacheTests.cs

Lines changed: 95 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public static async Task CacheOverflow2()
4444
{
4545
using (readSession)
4646
{
47+
Equal(key, readSession.Key);
4748
Equal(key.ToString(), readSession.Value);
4849
}
4950
}
@@ -68,6 +69,7 @@ public static async Task CacheOverflow2()
6869
public static async Task StressTest()
6970
{
7071
await using var cache = new RandomAccessCache<long, string>(15);
72+
Null(cache.KeyComparer);
7173

7274
const long accessCount = 1500;
7375

@@ -110,18 +112,21 @@ public static async Task AddRemoveAsync()
110112
{
111113
await using var cache = new RandomAccessCache<long, string>(15);
112114

113-
using (var session = await cache.ChangeAsync(10L))
115+
await using (var session = await cache.ChangeAsync(10L))
114116
{
115117
False(session.TryGetValue(out _));
116118
session.SetValue("10");
117119
}
118120

119121
Null(await cache.TryRemoveAsync(11L));
122+
True(cache.Contains(10L));
120123

121124
using (var session = (await cache.TryRemoveAsync(10L)).Value)
122125
{
123126
Equal("10", session.Value);
124127
}
128+
129+
False(cache.Contains(10L));
125130
}
126131

127132
[Fact]
@@ -136,12 +141,17 @@ public static void AddRemove()
136141
}
137142

138143
False(cache.TryRemove(11L, out _, DefaultTimeout));
144+
145+
True(cache.Contains(10L));
139146
True(cache.TryRemove(10L, out var session, DefaultTimeout));
147+
False(cache.Contains(10L));
140148

141149
using (session)
142150
{
143151
Equal("10", session.Value);
144152
}
153+
154+
False(cache.Contains(10L));
145155
}
146156

147157
[Fact]
@@ -229,6 +239,89 @@ public static async Task Invalidation()
229239
await cache.InvalidateAsync();
230240
}
231241

242+
[Fact]
243+
public static async Task ReplaceWhileReadingAsync()
244+
{
245+
await using var cache = new RandomAccessCache<long, string>(15);
246+
247+
using (var handle = await cache.ChangeAsync(42L))
248+
{
249+
handle.SetValue("42");
250+
}
251+
252+
True(cache.TryRead(42L, out var readSession));
253+
254+
using (readSession)
255+
{
256+
using (var handle = await cache.ReplaceAsync(42L))
257+
{
258+
False(handle.TryGetValue(out _));
259+
handle.SetValue("43");
260+
}
261+
262+
Equal("42", readSession.Value);
263+
}
264+
265+
True(cache.TryRead(42L, out readSession));
266+
267+
using (readSession)
268+
{
269+
Equal("43", readSession.Value);
270+
}
271+
}
272+
273+
[Fact]
274+
public static void ReplaceWhileReading()
275+
{
276+
using var cache = new RandomAccessCache<long, string>(15);
277+
278+
using (var handle = cache.Change(42L, DefaultTimeout))
279+
{
280+
handle.SetValue("42");
281+
}
282+
283+
True(cache.TryRead(42L, out var readSession));
284+
285+
using (readSession)
286+
{
287+
using (var handle = cache.Replace(42L, DefaultTimeout))
288+
{
289+
False(handle.TryGetValue(out _));
290+
handle.SetValue("43");
291+
}
292+
293+
Equal("42", readSession.Value);
294+
}
295+
296+
True(cache.TryRead(42L, out readSession));
297+
298+
using (readSession)
299+
{
300+
Equal("43", readSession.Value);
301+
}
302+
}
303+
304+
[Fact]
305+
public static void EnumeratePartially()
306+
{
307+
using var cache = new RandomAccessCache<long, string>(15);
308+
309+
using (var handle = cache.Change(42L, DefaultTimeout))
310+
{
311+
handle.SetValue("42");
312+
}
313+
314+
using (var handle = cache.Change(43L, DefaultTimeout))
315+
{
316+
handle.SetValue("43");
317+
}
318+
319+
using (var enumerator = cache.GetEnumerator())
320+
{
321+
True(enumerator.MoveNext());
322+
}
323+
}
324+
232325
[Fact]
233326
public static async Task EvictLargeItemImmediately()
234327
{
@@ -239,7 +332,7 @@ public static async Task EvictLargeItemImmediately()
239332
Eviction = (_, v) => source.TrySetResult(v),
240333
};
241334

242-
using (var session = await cache.ChangeAsync("101"))
335+
await using (var session = await cache.ChangeAsync("101"))
243336
{
244337
False(session.TryGetValue(out _));
245338
session.SetValue(101L); // 101 > 100, must be evicted immediately

0 commit comments

Comments
 (0)