Add polyfills for Interlocked.And and Interlocked.Or#80
Conversation
Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
…data types Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
| [Theory] | ||
| [InlineData((byte)0b00001111, (byte)0b11110000, (byte)0b00000000)] |
There was a problem hiding this comment.
Don't do theories. Just make one test that verifies a bunch of overloads at the same time.
There was a problem hiding this comment.
Done in 6c9a45b - replaced Theory tests with single Fact tests that verify multiple overloads.
PolyShim/Net100/Interlocked.cs
Outdated
| @@ -0,0 +1,197 @@ | |||
| #if (NETCOREAPP) || (NETFRAMEWORK) || (NETSTANDARD) | |||
There was a problem hiding this comment.
These generic methods (Interlocked.Or<T> and Interlocked.And<T>) were actually added in .NET 11 according to the API proposal (dotnet/runtime#114568). The non-generic overloads for int/uint/long/ulong exist in .NET 9, but the generic versions are .NET 11. Since NET11_0_OR_GREATER doesn't exist yet in the SDK, the polyfills remain active for now and will automatically be disabled once .NET 11 is released.
PolyShim/Net100/Interlocked.cs
Outdated
| #if (NETCOREAPP) || (NETFRAMEWORK) || (NETSTANDARD) | ||
| // NOTE: These polyfills will be automatically disabled when NET11_0_OR_GREATER is defined. | ||
| // Until then, they provide the generic And<T>/Or<T> methods for .NET 9 and 10. | ||
| #if NET9_0_OR_GREATER |
There was a problem hiding this comment.
Removed in 6c9a45b - the comment was unnecessary.
PolyShim/Net100/Interlocked.cs
Outdated
| [ExcludeFromCodeCoverage] | ||
| internal static class MemberPolyfills_Net100_Interlocked | ||
| { | ||
| extension(global::System.Threading.Interlocked) |
There was a problem hiding this comment.
Removed in 6c9a45b - changed to just System.Threading.Interlocked without the global:: prefix to match project style.
PolyShim/Net100/Interlocked.cs
Outdated
| where T : struct | ||
| { | ||
| // Only integer primitive types and enum types backed by integer types are supported. | ||
| // Floating-point types and floating-point backed enums are not supported. |
There was a problem hiding this comment.
Are floating point enums even a thing?
There was a problem hiding this comment.
You're right, they don't exist in C#. Removed that check in 6c9a45b - now only checking for float/double primitive types.
PolyShim/Net100/Interlocked.cs
Outdated
| } | ||
| } | ||
| #endif | ||
| #endif |
There was a problem hiding this comment.
What about the generic Interlocked.Exchange?
There was a problem hiding this comment.
Generic Interlocked.Exchange<T> already exists in .NET Core 2.0+ (according to MS docs), so it doesn't need a polyfill for the frameworks targeted by Net100.
…x conditionals Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
|
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
PolyShim/Net100/Interlocked.cs
Outdated
| [ExcludeFromCodeCoverage] | ||
| internal static class MemberPolyfills_Net100_Interlocked | ||
| { | ||
| extension(System.Threading.Interlocked) |
There was a problem hiding this comment.
Removed in 3c26340 - changed from System.Threading.Interlocked to just Interlocked to match the pattern in other Net100 files.
PolyShim/Net100/Interlocked.cs
Outdated
| extension(System.Threading.Interlocked) | ||
| { | ||
| // https://learn.microsoft.com/dotnet/api/system.threading.interlocked.and#system-threading-interlocked-and-1(-0@-0) | ||
| public static T And<T>(ref T location1, T value) |
There was a problem hiding this comment.
Can we have an overload for every type and have the generic overload delegate to what's appropriate? Same with Or
There was a problem hiding this comment.
Done in 3c26340 - added specific overloads for int, uint, long, and ulong. The generic methods now check the type and delegate to the appropriate specific overload when possible, falling back to size-based dispatch for enums.
…ification Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
|
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
Any way to polyfill these below net 5? @copilot |
The current implementation requires .NET 5.0+ due to the We could potentially lower the requirement from NET5_0 to include older frameworks like .NET Core 2.0+ and .NET Framework 4.6.1+ since those have To truly polyfill below .NET 9, we would need to implement the non-generic And/Or methods first (using CompareExchange loops), but that seems outside the scope of Net100 polyfills. |
|
How hard would it be to polyfill these APIs without Unsafe? @copilot |
It's feasible but with trade-offs: Non-generic overloads for uint/ulong: Could use unsafe pointers instead of unsafe { return *(uint*)&Interlocked.And(ref *(int*)&location1, *(int*)&value); }This would work on .NET Framework 4.5+ and other older frameworks. Generic overload: Much harder. Without
The cleanest approach would be to split the implementation:
Would you like me to implement the unsafe pointer approach to remove the System.Memory dependency? |
…ocks instead Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@copilot can you fix merge conflicts by following these steps:
|
Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
Done in commits f3c6f0e (reset), then merged master, and db95a53 (regenerated signatures). The merge conflicts are resolved and Signatures.md now correctly includes both the Interlocked methods and the TimeProvider/ITimer methods from master. Total: 372 signatures. |
Interlocked.And and Interlocked.Or
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #80 +/- ##
============================
============================
☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Adds polyfills for non-generic
Interlocked.AndandInterlocked.Ormethods (for int, uint, long, ulong types) introduced in .NET 5.0, enabling their use on all .NET Standard, .NET Framework, and .NET Core 1.0-4.x versions.Implementation
Polyfills (
PolyShim/Net50/Interlocked.cs):CompareExchangeloops (no dependencies)ALLOW_UNSAFE_BLOCKS)(NETCOREAPP && !NET5_0_OR_GREATER) || (NETFRAMEWORK) || (NETSTANDARD)Tests (
PolyShim.Tests/Net50/InterlockedTests.cs):Usage
Technical Details
CompareExchangeloops for atomic bitwise operations (no dependencies)unsafeblocks to delegate to int/long implementations (no dependencies)The implementation provides maximum framework support with zero external dependencies by using
CompareExchangeloops and unsafe pointers for type conversions. The polyfill signatures exactly match the actual .NET 5.0+ API surface - methods are not marked as unsafe even though they use unsafe code internally, ensuring perfect binary compatibility.Note
Generic overloads like
Interlocked.And<T>andInterlocked.Or<T>do not exist in .NET - onlyInterlocked.Exchange<T>andInterlocked.CompareExchange<T>have generic versions.Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.