//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
// UserRTX.NET satellite library | Author: Sergei Y.Kitáev
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
using System;
using System.Threading;

#if !WASM
namespace user_rtx { using u = user_rtx;
#else
namespace user_rtx.wasm { using u = user_rtx.wasm;
#endif

/// <summary>
/// Interlocked helpers
/// </summary>
public static class interlock {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

[u.returns_previous]
public static T? Reset<T>( [u.interlocked_access] ref T? operand )
where T: class =>
   Interlocked.Exchange( ref operand, null );

//==================================================================================================

public static T? Read<T>( [u.interlocked_access] ref T? location )
where T: class =>
   Interlocked.CompareExchange( ref location, null, null );

public static int Read( [u.interlocked_access] ref int location ) =>
   Interlocked.CompareExchange( ref location, 0, 0 );

//--------------------------------------------------------------------------------------------------

public static bool ReplaceIfNull<T>( [u.interlocked_access] ref T? location, T? subst )
where T: class =>
   CompareReplace<T>( ref location, subst, null );

public static bool CompareReplace<T>( [u.interlocked_access] ref T? location,
                                      T? subst, T? comparand )
where T: class
{
   T? opOriginal = Interlocked.CompareExchange( ref location, subst, comparand );
   return object.ReferenceEquals( opOriginal, comparand );
}

//==================================================================================================

[u.returns_target]
public static int Write( [u.interlocked_access] ref int location, int value )
{
   Interlocked.Exchange( ref location, value );
   return value;
}
[u.returns_target]
public static long Write( [u.interlocked_access] ref long location, long value )
{
   Interlocked.Exchange( ref location, value );
   return value;
}

[u.returns_target]
public static double Write( [u.interlocked_access] ref double location, double value )
{
   Interlocked.Exchange( ref location, value );
   return value;
}
[u.returns_target]
public static float Write( [u.interlocked_access] ref float location, float value )
{
   Interlocked.Exchange( ref location, value );
   return value;
}

[u.returns_target]
public static IntPtr Write( [u.interlocked_access] ref IntPtr location, IntPtr value )
{
   Interlocked.Exchange( ref location, value );
   return value;
}

//==================================================================================================

[u.returns_target]
public static T Write<T>( [u.interlocked_access] ref T location, T value )
where T: class
{
   Interlocked.Exchange( ref location, value );
   return value;
}

[u.returns_target]
public static T? WriteN<T>( [u.interlocked_access] ref T? location, T? value )
where T: class
{
   Interlocked.Exchange( ref location, value );
   return value;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // interlock

} // user_rtx (.wasm)
