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

namespace CommonHelpers {

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

public static unsafe readonly void*
   NullValue = (void*)HHandle.NullValue,
   InvalidValue = (void*)HHandle.InvalidValue;

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

public static unsafe bool IsNull(void* handle)
{
   return handle == NullValue;
}

public static unsafe bool IsInvalidValue(void* handle)
{
   return handle == InvalidValue;
}

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

public static unsafe bool IsInvalid(void* handle,bool isOfInvalidHandleValueCategory)
{
   return HHandle.IsInvalid( (IntPtr)handle, isOfInvalidHandleValueCategory );
}

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

public static unsafe void* GetNullOrInvalidValue(bool isOfInvalidHandleValueCategory)
{
   return (void*)HHandle.GetNullOrInvalidValue( isOfInvalidHandleValueCategory );
}

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

public static unsafe bool SimpleValidationCheck( [HOptional] void* handle,
                                                 bool isOfInvalidHandleValueCategory )
{
   return HHandle.SimpleValidationCheck(
      (IntPtr)handle, isOfInvalidHandleValueCategory );
}

public static unsafe void SimpleVerification( [HOptional] void* handle,
                                              bool isOfInvalidHandleValueCategory )
{
   HHandle.SimpleVerification( (IntPtr)handle, isOfInvalidHandleValueCategory );
}

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

public static unsafe void* Exchange(ref void* handle,void* subst)
{
   void* prev=handle; handle=subst; return prev;
}

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

public static unsafe void* NullValueExchange(ref void* handle)
{
   return Exchange(ref handle,NullValue);
}

public static unsafe void* InvalidValueExchange(ref void* handle)
{
   return Exchange(ref handle,InvalidValue);
}

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

public static unsafe void* InterlockedExchange( [HIn][HOut][HInterlockedAccess] void** pHandle,
                                                void* subst )
{
   return HUnsafeHandle.InterlockedExchange( pHandle, subst );
}

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

public static unsafe void* InterlockedNullValueExchange( [HIn][HOut][HInterlockedAccess]
                                                         void** pHandle )
{
   return InterlockedExchange( pHandle, NullValue );
}

public static unsafe void* InterlockedInvalidValueExchange( [HIn][HOut][HInterlockedAccess]
                                                            void** pHandle )
{
   return InterlockedExchange( pHandle, InvalidValue );
}

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

public static unsafe void* _InterlockedExchange( [HIn][HOut][HInterlockedAccess] void** pHandle,
                                                 void* subst )
{
   return InterlockedExchange( pHandle, subst );
}

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

public static unsafe void* Reset([HOptional][HIn][HOut][HInterlockedAccess] void** pHandle)
{
   return Reset( pHandle, false );
}

public static unsafe void* Reset( [HOptional][HIn][HOut][HInterlockedAccess] void** pHandle,
                                  bool isOfInvalidHandleValueCategory )
{
   return HUnsafePtr.InterlockedExchange( pHandle,
      isOfInvalidHandleValueCategory ? InvalidValue : NullValue );
}

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

/// <exception cref="Win32Exception" />
public static unsafe bool Close([HOptional] void* handle)
{
   return HHandle.Close( (IntPtr)handle );
}

/// <exception cref="Win32Exception" />
public static unsafe bool Close( [HOptional] void* handle,
                                 bool isOfInvalidHandleValueCategory )
{
   return HHandle.Close( (IntPtr)handle, isOfInvalidHandleValueCategory );
}

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

/// <exception cref="Win32Exception" />
public static unsafe bool Close( [HOptional] void* handle,
                                 [HOptional] HCloseHandleCallback closeHandleCallback )
{
   return HHandle.Close( (IntPtr)handle, closeHandleCallback );
}

/// <exception cref="Win32Exception" />
public static unsafe bool Close( [HOptional] void* handle,
                                 bool isOfInvalidHandleValueCategory,
                                 [HOptional] HCloseHandleCallback closeHandleCallback )
{
   return HHandle.Close( (IntPtr)handle, isOfInvalidHandleValueCategory, closeHandleCallback );
}

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

/// <exception cref="Win32Exception" />
public static unsafe bool SetNullAndClose([HOptional][HIn][HOut][HInterlockedAccess] void** pHandle)
{
   return Close( InterlockedNullValueExchange( pHandle ) );
}

/// <exception cref="Win32Exception" />
public static unsafe bool SetNullAndClose( [HOptional][HIn][HOut][HInterlockedAccess]
                                           void** pHandle,
                                           [HOptional] HCloseHandleCallback closeHandleCallback )
{
   return Close( InterlockedNullValueExchange( pHandle ), closeHandleCallback );
}

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

/// <exception cref="Win32Exception" />
public static unsafe bool InvalidateAndClose( [HOptional][HIn][HOut][HInterlockedAccess]
                                              void** pHandle )
{
   return Close( InterlockedInvalidValueExchange( pHandle ) );
}

/// <exception cref="Win32Exception" />
public static unsafe bool InvalidateAndClose
(
   [HOptional][HIn][HOut][HInterlockedAccess] void** pHandle,
   [HOptional] HCloseHandleCallback closeHandleCallback
)
{
   return Close( InterlockedInvalidValueExchange( pHandle ), closeHandleCallback );
}

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

/// <exception cref="Win32Exception" />
public static unsafe bool ResetAndClose( [HOptional][HIn][HOut][HInterlockedAccess] void** pHandle,
                                         bool isOfInvalidHandleValueCategory )
{
   return ResetAndClose( pHandle , isOfInvalidHandleValueCategory );
}

/// <exception cref="Win32Exception" />
public static unsafe bool ResetAndClose( [HOptional][HIn][HOut][HInterlockedAccess] void** pHandle,
                                         bool isOfInvalidHandleValueCategory,
                                         [HOptional] HCloseHandleCallback closeHandleCallback )
{
   return Close( Reset( pHandle, isOfInvalidHandleValueCategory ),
      isOfInvalidHandleValueCategory, closeHandleCallback );
}

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

static HUnsafeHandle()
{
   CommonHelpers_PAccess.Access();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // HUnsafeHandle
//**************************************************************************************************

} // CommonHelpers
