//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
// 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>
/// Thread helpers
/// </summary>
public static partial class thread {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

public const int
   PollInterval = u.asynch.PollInterval, // 100 (milliseconds)
   EnlargedPollInterval = u.asynch.EnlargedPollInterval; // 250 milliseconds

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

public static Thread CurrentThread => Thread.CurrentThread;

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

public static void Sleep( int milliseconds ) =>
   Thread.Sleep( milliseconds );

public static void Sleep( TimeSpan timeSpan ) =>
   Thread.Sleep( timeSpan );

public static void PollDelay() =>
   Thread.Sleep( u.asynch.PollInterval );

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

/// <exception cref="u.EAssertionFailed" />
public static u.EFake Hang()
{
   Thread.Sleep( Timeout.Infinite );
   throw u.assertion_fail.DEAD_BRANCH();
}

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

/// <exception cref="ThreadStateException" />
/// <exception cref="ThreadInterruptedException" />
[u.memory_barrier]
public static void Join( Thread thread )
{
   thread.Join();
   Thread.MemoryBarrier();
}

/// <exception cref="ThreadStateException" />
/// <exception cref="ThreadInterruptedException" />
[u.memory_barrier]
public static bool Join( Thread thread, int millisecondTimeout )
{
   bool joined = thread.Join( millisecondTimeout );
   if ( joined )
      Thread.MemoryBarrier();
   return joined;
}

/// <exception cref="ThreadStateException" />
/// <exception cref="ThreadInterruptedException" />
[u.memory_barrier]
public static bool Join( Thread thread, TimeSpan timeout )
{
   bool joined = thread.Join( timeout );
   if ( joined )
      Thread.MemoryBarrier();
   return joined;
}

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

/// <exception cref="ArgumentNullException" />
/// <exception cref="ThreadStateException" />
/// <exception cref="ThreadInterruptedException" />
[u.memory_barrier]
public static void SetNullAndJoin( [u.interlocked_access] ref Thread? thread )
{
   u.arg_check.NN( thread, nameof(thread) );
   Join( u.interlock.Reset( ref thread ).NN() );
}

/// <exception cref="ArgumentNullException" />
/// <exception cref="ArgumentException" />
/// <exception cref="ThreadStateException" />
/// <exception cref="ThreadInterruptedException" />
[u.memory_barrier]
public static bool SetNullAndJoin( [u.interlocked_access] ref Thread? thread,
                                   [u.not_negative] int millisecondTimeout )
{
   u.arg_check.NN( thread, nameof(thread) );
   u.arg_check.NotNegative( millisecondTimeout, nameof(millisecondTimeout) );
   return Join( u.interlock.Reset( ref thread ).NN(), millisecondTimeout );
}

/// <exception cref="ArgumentNullException" />
/// <exception cref="ThreadStateException" />
/// <exception cref="ThreadInterruptedException" />
[u.memory_barrier]
public static bool SetNullAndJoin( [u.interlocked_access] ref Thread? thread,
                                   [u.not_negative] TimeSpan timeout )
{
   u.arg_check.NN( thread, nameof(thread) );
   u.arg_check.NotNegative( timeout, nameof(timeout) );
   return Join( u.interlock.Reset( ref thread ).NN(), timeout );
}

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

/// <exception cref="ThreadStateException" />
/// <exception cref="OutOfMemoryException" />
[u.memory_barrier]
public static void Start( Thread thread )
{
   Thread.MemoryBarrier();
   thread.Start();
}

/// <exception cref="ThreadStateException" />
/// <exception cref="OutOfMemoryException" />
[u.memory_barrier]
public static void Start( Thread thread, object? parameter )
{
   Thread.MemoryBarrier();
   thread.Start( parameter );
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // thread

} // user_rtx (.wasm)
