Skip to content

Commit 15da57b

Browse files
committed
Bump HighPerformance package to .NET 7
1 parent 040b676 commit 15da57b

14 files changed

+58
-308
lines changed

CommunityToolkit.HighPerformance/CommunityToolkit.HighPerformance.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>netstandard2.0;netstandard2.1;netcoreapp3.1;net6.0</TargetFrameworks>
4+
<TargetFrameworks>netstandard2.0;netstandard2.1;netcoreapp3.1;net6.0;net7.0</TargetFrameworks>
55
</PropertyGroup>
66

77
<PropertyGroup>
@@ -45,7 +45,7 @@
4545
</ItemGroup>
4646
</When>
4747

48-
<When Condition="'$(TargetFramework)' == 'net6.0'">
48+
<When Condition="'$(TargetFramework)' == 'net6.0' OR '$(TargetFramework)' == 'net7.0'">
4949

5050
<!-- NETSTANDARD2_1_OR_GREATER: includes both .NET Standard 2.1, .NET Core 3.1 and .NET 6.
5151
Additionally, also enable trimming support on .NET 6. -->

CommunityToolkit.HighPerformance/Extensions/SpinLockExtensions.cs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using System;
56
using System.ComponentModel;
67
using System.Runtime.CompilerServices;
7-
#if NETSTANDARD2_1_OR_GREATER
8-
using System.Runtime.Versioning;
9-
#endif
108
using System.Threading;
119

1210
namespace CommunityToolkit.HighPerformance;
@@ -33,6 +31,8 @@ public static class SpinLockExtensions
3331
/// <returns>A wrapper type that will release <paramref name="spinLock"/> when its <see cref="System.IDisposable.Dispose"/> method is called.</returns>
3432
/// <remarks>The returned <see cref="UnsafeLock"/> value shouldn't be used directly: use this extension in a <see langword="using"/> block or statement.</remarks>
3533
[MethodImpl(MethodImplOptions.AggressiveInlining)]
34+
[Obsolete("Use SpinLockExtensions.Enter(ref SpinLock) instead.")]
35+
[EditorBrowsable(EditorBrowsableState.Never)]
3636
public static unsafe UnsafeLock Enter(SpinLock* spinLock)
3737
{
3838
return new(spinLock);
@@ -80,7 +80,7 @@ public void Dispose()
8080
}
8181
}
8282

83-
#if NETSTANDARD2_1_OR_GREATER
83+
#if NET7_0_OR_GREATER
8484
/// <summary>
8585
/// Enters a specified <see cref="SpinLock"/> instance and returns a wrapper to use to release the lock.
8686
/// This extension should be used though a <see langword="using"/> block or statement:
@@ -97,9 +97,6 @@ public void Dispose()
9797
/// <param name="spinLock">The target <see cref="SpinLock"/> to use</param>
9898
/// <returns>A wrapper type that will release <paramref name="spinLock"/> when its <see cref="System.IDisposable.Dispose"/> method is called.</returns>
9999
/// <remarks>The returned <see cref="Lock"/> value shouldn't be used directly: use this extension in a <see langword="using"/> block or statement.</remarks>
100-
[RequiresPreviewFeatures(
101-
"The Lock type has no compiler support to ensure the lifetime of referenced values is respected, and as such using it incorrectly may lead to GC holes.",
102-
Url = "https://github.com/dotnet/runtime/issues/46104")]
103100
[MethodImpl(MethodImplOptions.AggressiveInlining)]
104101
public static Lock Enter(ref this SpinLock spinLock)
105102
{
@@ -110,15 +107,12 @@ public static Lock Enter(ref this SpinLock spinLock)
110107
/// A <see langword="struct"/> that is used to enter and hold a <see cref="SpinLock"/> through a <see langword="using"/> block or statement.
111108
/// </summary>
112109
[EditorBrowsable(EditorBrowsableState.Never)]
113-
[RequiresPreviewFeatures(
114-
"The Lock type has no compiler support to ensure the lifetime of referenced values is respected, and as such using it incorrectly may lead to GC holes.",
115-
Url = "https://github.com/dotnet/runtime/issues/46104")]
116110
public readonly ref struct Lock
117111
{
118112
/// <summary>
119-
/// The <see cref="Ref{T}"/> instance pointing to the target <see cref="SpinLock"/> value to use.
113+
/// The reference to the target <see cref="SpinLock"/> value to use.
120114
/// </summary>
121-
private readonly Ref<SpinLock> spinLock;
115+
private readonly ref SpinLock spinLock;
122116

123117
/// <summary>
124118
/// A value indicating whether or not the lock is taken by this <see cref="Lock"/> instance.
@@ -132,7 +126,7 @@ public readonly ref struct Lock
132126
[MethodImpl(MethodImplOptions.AggressiveInlining)]
133127
internal Lock(ref SpinLock spinLock)
134128
{
135-
this.spinLock = new Ref<SpinLock>(ref spinLock);
129+
this.spinLock = ref spinLock;
136130
this.lockTaken = false;
137131

138132
spinLock.Enter(ref this.lockTaken);
@@ -146,7 +140,7 @@ public void Dispose()
146140
{
147141
if (this.lockTaken)
148142
{
149-
this.spinLock.Value.Exit();
143+
this.spinLock.Exit();
150144
}
151145
}
152146
}

CommunityToolkit.HighPerformance/NullableReadOnlyRef{T}.cs

Lines changed: 9 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,23 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5-
#if NETSTANDARD2_1_OR_GREATER
5+
#if NET7_0_OR_GREATER
66

77
using System;
88
using System.Runtime.CompilerServices;
9-
using System.Runtime.InteropServices;
10-
using System.Runtime.Versioning;
119

1210
namespace CommunityToolkit.HighPerformance;
1311

1412
/// <summary>
1513
/// A <see langword="struct"/> that can store an optional readonly reference to a value of a specified type.
1614
/// </summary>
1715
/// <typeparam name="T">The type of value to reference.</typeparam>
18-
[RequiresPreviewFeatures(
19-
"The NullableReadOnlyRef<T> type has no compiler support to ensure the lifetime of referenced values is respected, and as such using it incorrectly may lead to GC holes.",
20-
Url = "https://github.com/dotnet/runtime/issues/46104")]
2116
public readonly ref struct NullableReadOnlyRef<T>
2217
{
2318
/// <summary>
24-
/// The 1-length <see cref="ReadOnlySpan{T}"/> instance used to track the target <typeparamref name="T"/> value.
19+
/// The reference to the target <typeparamref name="T"/> value.
2520
/// </summary>
26-
private readonly ReadOnlySpan<T> span;
21+
private readonly ref readonly T value;
2722

2823
/// <summary>
2924
/// Initializes a new instance of the <see cref="NullableReadOnlyRef{T}"/> struct.
@@ -32,19 +27,7 @@ public readonly ref struct NullableReadOnlyRef<T>
3227
[MethodImpl(MethodImplOptions.AggressiveInlining)]
3328
public NullableReadOnlyRef(in T value)
3429
{
35-
ref T r0 = ref Unsafe.AsRef(value);
36-
37-
this.span = MemoryMarshal.CreateReadOnlySpan(ref r0, 1);
38-
}
39-
40-
/// <summary>
41-
/// Initializes a new instance of the <see cref="NullableReadOnlyRef{T}"/> struct.
42-
/// </summary>
43-
/// <param name="span">The <see cref="ReadOnlySpan{T}"/> instance to track the target <typeparamref name="T"/> reference.</param>
44-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
45-
private NullableReadOnlyRef(ReadOnlySpan<T> span)
46-
{
47-
this.span = span;
30+
this.value = ref value;
4831
}
4932

5033
/// <summary>
@@ -62,13 +45,7 @@ public static NullableReadOnlyRef<T> Null
6245
public unsafe bool HasValue
6346
{
6447
[MethodImpl(MethodImplOptions.AggressiveInlining)]
65-
get
66-
{
67-
// See comment in NullableRef<T> about this
68-
byte length = unchecked((byte)this.span.Length);
69-
70-
return *(bool*)&length;
71-
}
48+
get => !Unsafe.IsNullRef(ref Unsafe.AsRef(in this.value));
7249
}
7350

7451
/// <summary>
@@ -85,7 +62,7 @@ public ref readonly T Value
8562
ThrowInvalidOperationException();
8663
}
8764

88-
return ref MemoryMarshal.GetReference(this.span);
65+
return ref this.value;
8966
}
9067
}
9168

@@ -96,7 +73,7 @@ public ref readonly T Value
9673
[MethodImpl(MethodImplOptions.AggressiveInlining)]
9774
public static implicit operator NullableReadOnlyRef<T>(Ref<T> reference)
9875
{
99-
return new(reference.Span);
76+
return new(in reference.Value);
10077
}
10178

10279
/// <summary>
@@ -106,7 +83,7 @@ public static implicit operator NullableReadOnlyRef<T>(Ref<T> reference)
10683
[MethodImpl(MethodImplOptions.AggressiveInlining)]
10784
public static implicit operator NullableReadOnlyRef<T>(ReadOnlyRef<T> reference)
10885
{
109-
return new(reference.Span);
86+
return new(in reference.Value);
11087
}
11188

11289
/// <summary>
@@ -116,7 +93,7 @@ public static implicit operator NullableReadOnlyRef<T>(ReadOnlyRef<T> reference)
11693
[MethodImpl(MethodImplOptions.AggressiveInlining)]
11794
public static implicit operator NullableReadOnlyRef<T>(NullableRef<T> reference)
11895
{
119-
return new(reference.Span);
96+
return new(in reference.Value);
12097
}
12198

12299
/// <summary>

CommunityToolkit.HighPerformance/NullableRef{T}.cs

Lines changed: 7 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,23 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5-
#if NETSTANDARD2_1_OR_GREATER
5+
#if NET7_0_OR_GREATER
66

77
using System;
88
using System.Runtime.CompilerServices;
9-
using System.Runtime.InteropServices;
10-
using System.Runtime.Versioning;
119

1210
namespace CommunityToolkit.HighPerformance;
1311

1412
/// <summary>
1513
/// A <see langword="struct"/> that can store an optional reference to a value of a specified type.
1614
/// </summary>
1715
/// <typeparam name="T">The type of value to reference.</typeparam>
18-
[RequiresPreviewFeatures(
19-
"The NullableRef<T> type has no compiler support to ensure the lifetime of referenced values is respected, and as such using it incorrectly may lead to GC holes.",
20-
Url = "https://github.com/dotnet/runtime/issues/46104")]
2116
public readonly ref struct NullableRef<T>
2217
{
2318
/// <summary>
24-
/// The 1-length <see cref="Span{T}"/> instance used to track the target <typeparamref name="T"/> value.
19+
/// The reference to the target <typeparamref name="T"/> value.
2520
/// </summary>
26-
internal readonly Span<T> Span;
21+
private readonly ref T value;
2722

2823
/// <summary>
2924
/// Initializes a new instance of the <see cref="NullableRef{T}"/> struct.
@@ -32,17 +27,7 @@ public readonly ref struct NullableRef<T>
3227
[MethodImpl(MethodImplOptions.AggressiveInlining)]
3328
public NullableRef(ref T value)
3429
{
35-
this.Span = MemoryMarshal.CreateSpan(ref value, 1);
36-
}
37-
38-
/// <summary>
39-
/// Initializes a new instance of the <see cref="NullableRef{T}"/> struct.
40-
/// </summary>
41-
/// <param name="span">The <see cref="Span{T}"/> instance to track the target <typeparamref name="T"/> reference.</param>
42-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
43-
private NullableRef(Span<T> span)
44-
{
45-
this.Span = span;
30+
this.value = ref value;
4631
}
4732

4833
/// <summary>
@@ -60,19 +45,7 @@ public static NullableRef<T> Null
6045
public unsafe bool HasValue
6146
{
6247
[MethodImpl(MethodImplOptions.AggressiveInlining)]
63-
get
64-
{
65-
// We know that the span will always have a length of either
66-
// 1 or 0, so instead of using a cmp instruction and setting the
67-
// zero flag to produce our boolean value, we can just cast
68-
// the length to byte without overflow checks (doing a cast will
69-
// also account for the byte endianness of the current system),
70-
// and then reinterpret that value to a bool flag.
71-
// This results in a single movzx instruction on x86-64.
72-
byte length = unchecked((byte)this.Span.Length);
73-
74-
return *(bool*)&length;
75-
}
48+
get => !Unsafe.IsNullRef(ref this.value);
7649
}
7750

7851
/// <summary>
@@ -89,7 +62,7 @@ public ref T Value
8962
ThrowInvalidOperationException();
9063
}
9164

92-
return ref MemoryMarshal.GetReference(this.Span);
65+
return ref this.value;
9366
}
9467
}
9568

@@ -100,7 +73,7 @@ public ref T Value
10073
[MethodImpl(MethodImplOptions.AggressiveInlining)]
10174
public static implicit operator NullableRef<T>(Ref<T> reference)
10275
{
103-
return new(reference.Span);
76+
return new(ref reference.Value);
10477
}
10578

10679
/// <summary>

CommunityToolkit.HighPerformance/Properties/Polyfills/RequiresPreviewFeaturesAttribute.cs

Lines changed: 0 additions & 55 deletions
This file was deleted.

0 commit comments

Comments
 (0)