// RuntimeForStatic base library | C+- (SysRoutine) | Author: Sergei Y.Kitáev
#pragma once
#include "include_restrictions.h"
namespace RuntimeForStatic {
//==================================================================================================

template<typename T>static T $interlocked::Read($A,T volatile* pSource)
{
   $$VERIFY_POINTER_ARG( pSource );
   return (T)::InterlockedCompareExchange( (LONG volatile*)pSource, -1, -1 );
}
template<typename T>static T Write($A,T volatile* pTarget,T value) $ret_target
{
   $$VERIFY_POINTER_ARG( pTarget );
   ::InterlockedExchange( (LONG volatile*)pTarget, (LONG)value );
   return value;
}

template<typename T>static T $interlocked::Exchange($A,T volatile* pLocation,T value) $ret_previous
{
   $$VERIFY_POINTER_ARG( pLocation );
   return (T)::InterlockedExchange( (LONG volatile*)(PVOID)pLocation, (LONG)value );
}
template<typename T>static T $interlocked::CompareExchange($A, T volatile* pLocation,
                                                               T exchange, T comparand )
                                                               $ret_initial
{
   $$VERIFY_POINTER_ARG( pLocation );
   return (T)::InterlockedCompareExchange( (LONG volatile*)(PVOID)pLocation,
      (LONG)exchange, (LONG)comparand );
}

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

template<typename T>static T* $interlocked::ReadPointer($A,T* volatile* pPointer)
{
   $$VERIFY_POINTER_ARG( pPointer );
   return (T*)::InterlockedCompareExchangePointer( (PVOID volatile*)pPointer,
      (PVOID)-1, (PVOID)-1 );
}
template<typename T>static T* $interlocked::WritePointer($A, T* volatile* pTargetPtr,
                                                             T* pointerValue ) $ret_target
{
   $$VERIFY_POINTER_ARG( pTargetPtr );
   ::InterlockedExchangePointer( (PVOID volatile*)pTargetPtr, pointerValue );
   return pointerValue;
}

template<typename T>static T* $interlocked::ExchangePointer($A, T* volatile* pPointer,
                                                                T* pointerValue ) $ret_previous
{
   $$VERIFY_POINTER_ARG( pPointer );
   return (T*)::InterlockedExchangePointer( (PVOID volatile*)pPointer, pointerValue );
}
template<typename T>static T* $interlocked::CompareExchangePointer($A, T* volatile* pPointer,
                                                                       T* exchangePtr,
                                                                       T* comparandPtr )
                                                                       $ret_initial
{
   $$VERIFY_POINTER_ARG( pPointer );
   return (T*)::InterlockedCompareExchangePointer( (PVOID volatile*)pPointer,
      exchangePtr, comparandPtr );
}
template<typename T>static T* $interlocked::ResetPointer($A, T* volatile* pPointer )
                                                             $ret_previous
{
   return ExchangePointer<T>($ci, pPointer, nullptr );
}

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

template<typename T>static const T* $interlocked::ReadPointerC($A,const T* volatile* pPointer)
{
   $$VERIFY_POINTER_ARG( pPointer );
   return (const T*)::InterlockedCompareExchangePointer( (PVOID volatile*)pPointer,
      (PVOID)-1, (PVOID)-1 );
}
template<typename T>static const T* $interlocked::WritePointerC($A, const T* volatile* pTargetPtr,
                                                                    const T* pointerValue )
                                                                    $ret_target
{
   $$VERIFY_POINTER_ARG( pTargetPtr );
   ::InterlockedExchangePointer( (PVOID volatile*)pTargetPtr, (PVOID)pointerValue );
   return pointerValue;
}

template<typename T>static const T* $interlocked::ExchangePointerC($A,
   const T* volatile* pPointer,
   const T* pointerValue ) $ret_previous
{
   $$VERIFY_POINTER_ARG( pPointer );
   return (const T*)::InterlockedCompareExchangePointer( (PVOID volatile*)pPointer,
                                                         (PVOID)pointerValue );
}
template<typename T>static const T* $interlocked::CompareExchangePointerC($A,
   const T* volatile* pPointer,
   const T* exchangePtr,
   const T* comparandPtr ) $ret_initial
{
   $$VERIFY_POINTER_ARG( pPointer );
   return (const T*)::InterlockedCompareExchangePointer(
      (PVOID volatile*)pPointer, (PVOID)exchangePtr, (PVOID)comparandPtr );
}
template<typename T>static T* $interlocked::ResetPointerC($A, const T* volatile* pPointer )
                                                              $ret_previous
{
   return ExchangePointerC<T>($ci, pPointer, nullptr );
}

//==================================================================================================
} // RuntimeForStatic
