diff --git a/PolyShim.Tests/Net50/InterlockedTests.cs b/PolyShim.Tests/Net50/InterlockedTests.cs new file mode 100644 index 0000000..8743c23 --- /dev/null +++ b/PolyShim.Tests/Net50/InterlockedTests.cs @@ -0,0 +1,59 @@ +using System.Threading; +using FluentAssertions; +using Xunit; + +namespace PolyShim.Tests.Net50; + +public class InterlockedTests +{ + [Fact] + public void And_Test() + { + // uint + uint ui = 0xFFFFFFFF; + Interlocked.And(ref ui, 0xAAAAAAAA).Should().Be(0xFFFFFFFF); + ui.Should().Be(0xAAAAAAAA); + + // int + int i = unchecked((int)0xFFFFFFFF); + Interlocked.And(ref i, unchecked((int)0xAAAAAAAA)).Should().Be(unchecked((int)0xFFFFFFFF)); + i.Should().Be(unchecked((int)0xAAAAAAAA)); + + // ulong + ulong ul = 0xFFFFFFFFFFFFFFFF; + Interlocked.And(ref ul, 0xAAAAAAAAAAAAAAAA).Should().Be(0xFFFFFFFFFFFFFFFF); + ul.Should().Be(0xAAAAAAAAAAAAAAAA); + + // long + long l = unchecked((long)0xFFFFFFFFFFFFFFFF); + Interlocked + .And(ref l, unchecked((long)0xAAAAAAAAAAAAAAAA)) + .Should() + .Be(unchecked((long)0xFFFFFFFFFFFFFFFF)); + l.Should().Be(unchecked((long)0xAAAAAAAAAAAAAAAA)); + } + + [Fact] + public void Or_Test() + { + // uint + uint ui = 0x0000FFFF; + Interlocked.Or(ref ui, 0xFFFF0000).Should().Be(0x0000FFFF); + ui.Should().Be(0xFFFFFFFF); + + // int + int i = 0x0000FFFF; + Interlocked.Or(ref i, unchecked((int)0xFFFF0000)).Should().Be(0x0000FFFF); + i.Should().Be(unchecked((int)0xFFFFFFFF)); + + // ulong + ulong ul = 0x00000000FFFFFFFF; + Interlocked.Or(ref ul, 0xFFFFFFFF00000000).Should().Be(0x00000000FFFFFFFF); + ul.Should().Be(0xFFFFFFFFFFFFFFFF); + + // long + long l = 0x00000000FFFFFFFF; + Interlocked.Or(ref l, unchecked((long)0xFFFFFFFF00000000)).Should().Be(0x00000000FFFFFFFF); + l.Should().Be(unchecked((long)0xFFFFFFFFFFFFFFFF)); + } +} diff --git a/PolyShim/Net50/Interlocked.cs b/PolyShim/Net50/Interlocked.cs new file mode 100644 index 0000000..576834e --- /dev/null +++ b/PolyShim/Net50/Interlocked.cs @@ -0,0 +1,142 @@ +#if (NETCOREAPP && !NET5_0_OR_GREATER) || (NETFRAMEWORK) || (NETSTANDARD) +#nullable enable +// ReSharper disable RedundantUsingDirective +// ReSharper disable CheckNamespace +// ReSharper disable InconsistentNaming +// ReSharper disable PartialTypeWithSinglePart + +using System.Diagnostics.CodeAnalysis; +using System.Threading; + +[ExcludeFromCodeCoverage] +internal static class MemberPolyfills_Net50_Interlocked +{ + extension(Interlocked) + { + // https://learn.microsoft.com/dotnet/api/system.threading.interlocked.and#system-threading-interlocked-and(system-int32@-system-int32) + public static int And(ref int location1, int value) + { + int current, + newValue, + original; + do + { + current = location1; + newValue = current & value; + original = Interlocked.CompareExchange(ref location1, newValue, current); + } while (original != current); + + return original; + } + +#if ALLOW_UNSAFE_BLOCKS + // https://learn.microsoft.com/dotnet/api/system.threading.interlocked.and#system-threading-interlocked-and(system-uint32@-system-uint32) + public static uint And(ref uint location1, uint value) + { + unsafe + { + fixed (uint* ptr = &location1) + { + int result = Interlocked.And(ref *(int*)ptr, *(int*)&value); + return *(uint*)&result; + } + } + } +#endif + + // https://learn.microsoft.com/dotnet/api/system.threading.interlocked.and#system-threading-interlocked-and(system-int64@-system-int64) + public static long And(ref long location1, long value) + { + long current, + newValue, + original; + do + { + current = location1; + newValue = current & value; + original = Interlocked.CompareExchange(ref location1, newValue, current); + } while (original != current); + + return original; + } + +#if ALLOW_UNSAFE_BLOCKS + // https://learn.microsoft.com/dotnet/api/system.threading.interlocked.and#system-threading-interlocked-and(system-uint64@-system-uint64) + public static ulong And(ref ulong location1, ulong value) + { + unsafe + { + fixed (ulong* ptr = &location1) + { + long result = Interlocked.And(ref *(long*)ptr, *(long*)&value); + return *(ulong*)&result; + } + } + } +#endif + + // https://learn.microsoft.com/dotnet/api/system.threading.interlocked.or#system-threading-interlocked-or(system-int32@-system-int32) + public static int Or(ref int location1, int value) + { + int current, + newValue, + original; + do + { + current = location1; + newValue = current | value; + original = Interlocked.CompareExchange(ref location1, newValue, current); + } while (original != current); + + return original; + } + +#if ALLOW_UNSAFE_BLOCKS + // https://learn.microsoft.com/dotnet/api/system.threading.interlocked.or#system-threading-interlocked-or(system-uint32@-system-uint32) + public static uint Or(ref uint location1, uint value) + { + unsafe + { + fixed (uint* ptr = &location1) + { + int result = Interlocked.Or(ref *(int*)ptr, *(int*)&value); + return *(uint*)&result; + } + } + } +#endif + + // https://learn.microsoft.com/dotnet/api/system.threading.interlocked.or#system-threading-interlocked-or(system-int64@-system-int64) + public static long Or(ref long location1, long value) + { + long current, + newValue, + original; + do + { + current = location1; + newValue = current | value; + original = Interlocked.CompareExchange(ref location1, newValue, current); + } while (original != current); + + return original; + } + +#if ALLOW_UNSAFE_BLOCKS + // https://learn.microsoft.com/dotnet/api/system.threading.interlocked.or#system-threading-interlocked-or(system-uint64@-system-uint64) + public static ulong Or(ref ulong location1, ulong value) + { + unsafe + { + fixed (ulong* ptr = &location1) + { + long result = Interlocked.Or(ref *(long*)ptr, *(long*)&value); + return *(ulong*)&result; + } + } + } +#endif + } +} + +#endif diff --git a/PolyShim/Signatures.md b/PolyShim/Signatures.md index 5456834..8a19aca 100644 --- a/PolyShim/Signatures.md +++ b/PolyShim/Signatures.md @@ -1,8 +1,8 @@ # Signatures -- **Total:** 364 +- **Total:** 372 - **Types:** 78 -- **Members:** 286 +- **Members:** 294 ___ @@ -175,6 +175,15 @@ ___ - [**[struct]**](https://learn.microsoft.com/dotnet/api/system.index) .NET Core 3.0 - `int` - [`bool TryParse(string, IFormatProvider?, out int)`](https://learn.microsoft.com/dotnet/api/system.int32.tryparse#system-int32-tryparse(system-string-system-iformatprovider-system-int32@)) .NET 7.0 +- `Interlocked` + - [`int And(ref int, int)`](https://learn.microsoft.com/dotnet/api/system.threading.interlocked.and#system-threading-interlocked-and(system-int32@-system-int32)) .NET 5.0 + - [`int Or(ref int, int)`](https://learn.microsoft.com/dotnet/api/system.threading.interlocked.or#system-threading-interlocked-or(system-int32@-system-int32)) .NET 5.0 + - [`long And(ref long, long)`](https://learn.microsoft.com/dotnet/api/system.threading.interlocked.and#system-threading-interlocked-and(system-int64@-system-int64)) .NET 5.0 + - [`long Or(ref long, long)`](https://learn.microsoft.com/dotnet/api/system.threading.interlocked.or#system-threading-interlocked-or(system-int64@-system-int64)) .NET 5.0 + - [`uint And(ref uint, uint)`](https://learn.microsoft.com/dotnet/api/system.threading.interlocked.and#system-threading-interlocked-and(system-uint32@-system-uint32)) .NET 5.0 + - [`uint Or(ref uint, uint)`](https://learn.microsoft.com/dotnet/api/system.threading.interlocked.or#system-threading-interlocked-or(system-uint32@-system-uint32)) .NET 5.0 + - [`ulong And(ref ulong, ulong)`](https://learn.microsoft.com/dotnet/api/system.threading.interlocked.and#system-threading-interlocked-and(system-uint64@-system-uint64)) .NET 5.0 + - [`ulong Or(ref ulong, ulong)`](https://learn.microsoft.com/dotnet/api/system.threading.interlocked.or#system-threading-interlocked-or(system-uint64@-system-uint64)) .NET 5.0 - `IntPtr` - [`bool TryParse(string, IFormatProvider?, out IntPtr)`](https://learn.microsoft.com/dotnet/api/system.intptr.tryparse#system-intptr-tryparse(system-string-system-iformatprovider-system-intptr@)) .NET 7.0 - [`bool TryParse(string?, out IntPtr)`](https://learn.microsoft.com/dotnet/api/system.intptr.tryparse#system-intptr-tryparse(system-string-system-intptr@)) .NET 5.0