2022-11-30 11:11:18 +00:00
/***
Copyright ( C ) 2022 J Reece Wilson ( a / k / a " Reece " ) . All rights reserved .
File : ErrorStack . cpp
Date : 2022 - 11 - 29
Author : Reece
* * */
# include <Source/RuntimeInternal.hpp>
# include "Debug.hpp"
# include "ErrorStack.hpp"
2023-08-27 11:41:51 +00:00
# if defined(AURORA_COMPILER_CLANG)
// warning: ISO C++20 considers use of overloaded operator '==' (with operand types 'AuSPtr<Aurora::Debug::ThreadMessage>' (aka 'ExSharedPtr<Aurora::Debug::ThreadMessage, std::shared_ptr<ThreadMessage>>') and 'AuSPtr<Aurora::Debug::ThreadMessage>' (aka 'ExSharedPtr<Aurora::Debug::ThreadMessage, std::shared_ptr<ThreadMessage>>')) to be ambiguous despite there being a unique best viable function [-Wambiguous-reversed-operator]
# pragma clang diagnostic ignored "-Wambiguous-reversed-operator"
// Yea, I couldn't give less of a nanoshit what some C++20 spec says. Even llvm/clang doesn't care to language police it into a fatal unimplemented compiler condition. So, idc.
# endif
2022-11-30 11:11:18 +00:00
namespace Aurora : : Debug
{
2024-02-14 00:32:30 +00:00
static thread_local AuString tlsLastMessageError ;
static AuString strFailureCategoryCache [ 128 ] ;
2022-11-30 11:11:18 +00:00
struct ErrorStackAccessor
{
void SetNext ( ErrorStack * pStack , ErrorStack * pNext )
{
pStack - > pNext = pNext ;
}
ErrorStack * GetNext ( ErrorStack * pStack )
{
return pStack - > pNext ;
}
void SetHead ( ErrorStack * pStack , AuSPtr < ThreadMessage > pHead )
{
pStack - > pHead = pHead ;
}
AuSPtr < ThreadMessage > GetHead ( ErrorStack * pStack )
{
return pStack - > pHead ;
}
2024-02-14 00:32:30 +00:00
void SetOOM ( ErrorStack * pStack )
{
pStack - > bOutOfMemory = true ;
}
2022-11-30 11:11:18 +00:00
} ;
2024-02-14 00:32:30 +00:00
AUKN_SYM const AuString & ThreadMessage : : ToString ( )
2022-11-30 11:11:18 +00:00
{
if ( this - > pStringMessage )
{
return * this - > pStringMessage ;
}
if ( eFailureCategory )
{
2024-02-14 00:32:30 +00:00
auto uIndex = ( AuUInt ) * eFailureCategory ;
if ( AuArraySize ( strFailureCategoryCache ) < = uIndex )
{
return tlsLastMessageError = fmt : : format ( " Debug::EFailureCategory = {} " , ( AuUInt ) * eFailureCategory ) ;
}
else
{
auto & stringBuffer = strFailureCategoryCache [ uIndex ] ;
if ( stringBuffer . size ( ) )
{
return stringBuffer ;
}
else
{
return stringBuffer = fmt : : format ( " Debug::EFailureCategory = {} " , ( AuUInt ) * eFailureCategory ) ;
}
}
2022-11-30 11:11:18 +00:00
}
if ( optOsErrorCode )
{
2024-02-14 00:32:30 +00:00
return tlsLastMessageError = fmt : : format ( " OS = {} " , ( AuUInt ) * optOsErrorCode ) ;
2022-11-30 11:11:18 +00:00
}
return " Unknown error. " ;
}
static thread_local ErrorStack * tlsErrorStackBase ;
2023-03-22 18:11:32 +00:00
AUKN_SYM ErrorStack : : ErrorStack ( )
2022-11-30 11:11:18 +00:00
{
2023-03-22 18:11:32 +00:00
auto pStack = this ;
2022-11-30 11:11:18 +00:00
if ( ! tlsErrorStackBase )
{
tlsErrorStackBase = pStack ;
return ;
}
ErrorStackAccessor dumb ;
auto itr = tlsErrorStackBase ;
while ( auto pNext = dumb . GetNext ( itr ) )
{
itr = pNext ;
}
dumb . SetNext ( itr , pStack ) ;
}
2023-03-22 18:11:32 +00:00
AUKN_SYM ErrorStack : : ~ ErrorStack ( )
2022-11-30 11:11:18 +00:00
{
2023-03-22 18:11:32 +00:00
auto pStack = this ;
2022-11-30 11:11:18 +00:00
if ( ! tlsErrorStackBase )
{
return ;
}
ErrorStackAccessor dumb ;
auto itr = tlsErrorStackBase ;
if ( itr = = pStack )
{
tlsErrorStackBase = nullptr ;
return ;
}
while ( auto pNext = dumb . GetNext ( itr ) )
{
if ( pNext = = pStack )
{
dumb . SetNext ( pStack , { } ) ;
return ;
}
itr = pNext ;
}
}
static void AddToInstance ( ErrorStack * pStack , AuSPtr < ThreadMessage > pMessage )
{
ErrorStackAccessor dumb ;
if ( ! dumb . GetHead ( pStack ) )
{
dumb . SetHead ( pStack , pMessage ) ;
return ;
}
AuSPtr < ThreadMessage > pMessage2 { dumb . GetHead ( pStack ) } ;
if ( pMessage2 = = pMessage )
{
return ;
}
while ( auto pNext = pMessage2 - > pNextThreadMesage )
{
if ( pNext = = pMessage )
{
return ;
}
pMessage2 = pNext ;
}
pMessage2 - > pNextThreadMesage = pMessage ;
}
//////////////////////////////////////////////////////////////////
// internal api:
bool ShouldPushErrorStackInternal ( )
{
return bool ( tlsErrorStackBase ) ;
}
void PushErrorStackInternal ( AuSPtr < ThreadMessage > pMessage )
{
ErrorStackAccessor dumb ;
auto itr = tlsErrorStackBase ;
if ( itr )
{
AddToInstance ( itr , pMessage ) ;
while ( auto pNext = dumb . GetNext ( itr ) )
{
AddToInstance ( itr , pMessage ) ;
itr = pNext ;
}
}
}
2024-02-14 00:32:30 +00:00
void OnOutOfMemory ( )
{
ErrorStackAccessor dumb ;
auto itr = tlsErrorStackBase ;
if ( itr )
{
dumb . SetOOM ( itr ) ;
while ( auto pNext = dumb . GetNext ( itr ) )
{
dumb . SetOOM ( itr ) ;
itr = pNext ;
}
}
}
2022-11-30 11:11:18 +00:00
}