Background and motivation
I would like to do something like this:
struct MyStruct {
public int Value;
}
unsafe class MyClass {
MyStruct* _myStruct;
MyStruct* CreateOnce ()
{
var ptr = (MyStruct *) NativeMemory.AllocZeroed ((nuint) sizeof (MyStruct));
var oldPtr = Interlocked.CompareExchange (ref _myStruct, ptr, null);
if (oldPtr is not null {
NativeMemory.Free (ptr);
return oldPtr;
}
return ptr;
}
}
but it doesn't compile:
The type 'MyStruct*' may not be used as a type argument
I wrote this helper method, which works:
internal unsafe static T* InterlockedCompareExchange<T> (ref T* location1, T* value, T* comparand) where T: unmanaged
{
fixed (T** ptr = &location1) {
return (T *) Interlocked.CompareExchange (ref Unsafe.AsRef<IntPtr> (ptr), (IntPtr) value, (IntPtr) comparand);
}
}
but ugh... and I don't really know if it's safe or not either.
API Proposal
namespace System.Collections.Generic;
public class Interlocked
{
public unsafe static T* CompareExchange<T> (ref T* location1, T* value, T* comparand) where T: unmanaged;
}
API Usage
struct MyStruct {
public int Value;
}
unsafe class MyClass {
MyStruct* _myStruct;
MyStruct* CreateOnce ()
{
var ptr = (MyStruct *) NativeMemory.AllocZeroed ((nuint) sizeof (MyStruct));
var oldPtr = Interlocked.CompareExchange<MyStruct> (ref _myStruct, ptr, null);
if (oldPtr is not null {
NativeMemory.Free (ptr);
return oldPtr;
}
return ptr;
}
}
Alternative Designs
Keep using either my scary-looking InterlockedCompareExchange solution, or use IntPtr (which is somewhat error prone too):
struct MyStruct {
public int Value;
}
unsafe class MyClass {
IntPtr _myStruct;
MyStruct* CreateOnce ()
{
var ptr = (IntPtr) NativeMemory.AllocZeroed ((nuint) sizeof (MyStruct));
var oldPtr = Interlocked.CompareExchange (ref _myStruct, ptr, IntPtr.Zero);
if (oldPtr is not null {
NativeMemory.Free (ptr);
return (MyStruct *) oldPtr;
}
return (MyStruct *) ptr;
}
}
Risks
Not sure if the proposed overload might conflict with the existing generic overload.
There might be other Interlocked APIs that this would apply to as well, I haven't looked.
Background and motivation
I would like to do something like this:
but it doesn't compile:
I wrote this helper method, which works:
but ugh... and I don't really know if it's safe or not either.
API Proposal
API Usage
Alternative Designs
Keep using either my scary-looking
InterlockedCompareExchangesolution, or use IntPtr (which is somewhat error prone too):Risks
Not sure if the proposed overload might conflict with the existing generic overload.
There might be other Interlocked APIs that this would apply to as well, I haven't looked.