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

$Disposable::$Disposable()
: $Disposable( false )
{}
$Disposable::$Disposable(bool interlockedAccess)
{
   $CLEAR_INSTANCE();
   _InterlockedAccess_ = interlockedAccess;
}

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

bool $Disposable::GetInterlockedAccess() const
{
   return _InterlockedAccess_;
}
bool $Disposable::GetWasCreated() const
{
   return _WasCreated_;
}

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

bool $Disposable::GetIsValidDisposable() const
{
   return InterlockedAccess ?
      $Interlocked::GetAsBool($, &_IsValidDisposable_ ) :
      _IsValidDisposable_;
}
bool $Disposable::GetDisposed() const
{
   return InterlockedAccess ?
      $Interlocked::GetAsBool($, &_Disposed_ ) :
      _Disposed_;
}
bool $Disposable::GetDisposing() const
{
   return InterlockedAccess ?
      $Interlocked::GetAsBool($, &_Disposing_ ) :
      _Disposing_;
}

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

void $Disposable::VerifyValidDisposable($O) const
{
   if ( !IsValidDisposable )
      $FatalError::RaiseNotValidDisposable($$CI);
}

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

$Disposable::~$Disposable()
{
   Dispose();
}

bool $Disposable::Dispose()
{
   if ( !IsValidDisposable )
      return false;
   if ( InterlockedAccess )
   {
      if ( $Interlocked::ExchangeAsBool($, &_DisposeStarted_, true ) )
         return false;
      $Interlocked::SetAsBool($, &_Disposing_ );
   }
   else
   {
      if ( _DisposeStarted_ )
         return false;
      _DisposeStarted_ = true;
      _Disposing_ = true;
   }
   $$VERIFY_POINTER( _ValidationCIPtr_ );
   $WITH_FINALLY
   {
      DoDispose( *_ValidationCIPtr_ );
   }
   $FINALIZATION
   {
      InvalidateDisposable();
      if ( InterlockedAccess )
      {
         $Interlocked::ResetAsBool($, &_Disposing_ );
         $Interlocked::SetAsBool($, &_Disposed_ );
      }
      else
      {
         _Disposing_ = false;
         _Disposed_ = true;
      }
   }
   $END_FINALLY;
   return true;
}

void $Disposable::DoDispose($CI_REF) $nop
{}

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

void $Disposable::ValidateDisposable($CI_REF)
{
   if ( WasCreated )
      $FatalError::RaiseDisposableWasAlreadyCreated($$CI);
   if ( InterlockedAccess )
      $Interlocked::SetAsBool($, &_IsValidDisposable_ );
   else
      _IsValidDisposable_ = true;
   _ValidationCIPtr_ = &$$CI;
   _WasCreated_ = true;
}

void $Disposable::InvalidateDisposable()
{
   if ( InterlockedAccess )
      $Interlocked::ResetAsBool($, &_IsValidDisposable_ );
   else
      _IsValidDisposable_ = false;
}

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