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

#if !WASM
namespace CommonHelpers {
#else
namespace CommonHelpers.WASM {
#endif

//**************************************************************************************************
/// <summary>
/// </summary>
public static partial class HAsyncResult {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/// <exception cref="ObjectDisposedException" />
/// <exception cref="AbandonedMutexException" />
/// <exception cref="InvalidOperationException" />
public static bool? WaitOneAndCloseHandleIfNotNull([HOptional] IAsyncResult asyncResult)
{
   if ( asyncResult == null ) return null;
   asyncResult.AsyncWaitHandle.WaitOne();
   asyncResult.AsyncWaitHandle.Close();
   return true;
}

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

/// <exception cref="ObjectDisposedException" />
/// <exception cref="AbandonedMutexException" />
/// <exception cref="InvalidOperationException" />
/// <exception cref="ArgumentOutOfRangeException" />
public static bool? WaitOneAndCloseHandleIfNotNull( [HOptional] IAsyncResult asyncResult,
                                                    int millisecondsTimeout )
{
   if ( asyncResult == null ) return null;
   bool wres = asyncResult.AsyncWaitHandle.WaitOne( millisecondsTimeout );
   if ( wres ) asyncResult.AsyncWaitHandle.Close(); return wres;
}

/// <exception cref="ObjectDisposedException" />
/// <exception cref="AbandonedMutexException" />
/// <exception cref="InvalidOperationException" />
/// <exception cref="ArgumentOutOfRangeException" />
public static bool? WaitOneAndCloseHandleIfNotNull( [HOptional] IAsyncResult asyncResult,
                                                    TimeSpan timeout )
{
   if ( asyncResult == null ) return null;
   bool wres = asyncResult.AsyncWaitHandle.WaitOne( timeout );
   if ( wres ) asyncResult.AsyncWaitHandle.Close(); return wres;
}

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

/// <exception cref="ObjectDisposedException" />
/// <exception cref="AbandonedMutexException" />
/// <exception cref="InvalidOperationException" />
/// <exception cref="ArgumentOutOfRangeException" />
public static bool? WaitOneAndCloseHandleIfNotNull( [HOptional] IAsyncResult asyncResult,
                                                    int millisecondsTimeout,
                                                    bool exitContext )
{
   if ( asyncResult == null ) return null;
   bool wres = asyncResult.AsyncWaitHandle.WaitOne( millisecondsTimeout, exitContext );
   if ( wres ) asyncResult.AsyncWaitHandle.Close(); return wres;
}

/// <exception cref="ObjectDisposedException" />
/// <exception cref="AbandonedMutexException" />
/// <exception cref="InvalidOperationException" />
/// <exception cref="ArgumentOutOfRangeException" />
public static bool? WaitOneAndCloseHandleIfNotNull( [HOptional] IAsyncResult asyncResult,
                                                    TimeSpan timeout,
                                                    bool exitContext )
{
   if ( asyncResult == null ) return null;
   bool wres = asyncResult.AsyncWaitHandle.WaitOne( timeout, exitContext );
   if ( wres ) asyncResult.AsyncWaitHandle.Close(); return wres;
}

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

/// <exception cref="ObjectDisposedException" />
/// <exception cref="AbandonedMutexException" />
/// <exception cref="InvalidOperationException" />
[CLSCompliant(false)]
public static bool? WaitOneAndCloseHandleIfNotNull( [HOptional][HInterlockedAccess]
                                                    ref IAsyncResult asyncResult )
{
   return WaitOneAndCloseHandleIfNotNull( HInterlocked.NullExchange(ref asyncResult) );
}

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

/// <exception cref="ObjectDisposedException" />
/// <exception cref="AbandonedMutexException" />
/// <exception cref="InvalidOperationException" />
/// <exception cref="ArgumentOutOfRangeException" />
[CLSCompliant(false)]
public static bool? WaitOneAndCloseHandleIfNotNull( [HOptional][HInterlockedAccess]
                                                    ref IAsyncResult asyncResult,
                                                    int millisecondsTimeout )
{
   return WaitOneAndCloseHandleIfNotNull(
      HInterlocked.NullExchange(ref asyncResult), millisecondsTimeout );
}

/// <exception cref="ObjectDisposedException" />
/// <exception cref="AbandonedMutexException" />
/// <exception cref="InvalidOperationException" />
/// <exception cref="ArgumentOutOfRangeException" />
[CLSCompliant(false)]
public static bool? WaitOneAndCloseHandleIfNotNull( [HOptional][HInterlockedAccess]
                                                    ref IAsyncResult asyncResult,
                                                    TimeSpan timeout )
{
   return WaitOneAndCloseHandleIfNotNull( HInterlocked.NullExchange(ref asyncResult), timeout );
}

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

/// <exception cref="ObjectDisposedException" />
/// <exception cref="AbandonedMutexException" />
/// <exception cref="InvalidOperationException" />
/// <exception cref="ArgumentOutOfRangeException" />
[CLSCompliant(false)]
public static bool? WaitOneAndCloseHandleIfNotNull( [HOptional][HInterlockedAccess]
                                                    ref IAsyncResult asyncResult,
                                                    int millisecondsTimeout, bool exitContext )
{
   return WaitOneAndCloseHandleIfNotNull(
      HInterlocked.NullExchange(ref asyncResult), millisecondsTimeout, exitContext );
}

/// <exception cref="ObjectDisposedException" />
/// <exception cref="AbandonedMutexException" />
/// <exception cref="InvalidOperationException" />
/// <exception cref="ArgumentOutOfRangeException" />
[CLSCompliant(false)]
public static bool? WaitOneAndCloseHandleIfNotNull( [HOptional][HInterlockedAccess]
                                                    ref IAsyncResult asyncResult,
                                                    TimeSpan timeout, bool exitContext )
{
   return WaitOneAndCloseHandleIfNotNull(
      HInterlocked.NullExchange(ref asyncResult), timeout, exitContext );
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // HAsyncResult
//**************************************************************************************************

} // CommonHelpers (.WASM)
