208 lines
5.2 KiB
C++
208 lines
5.2 KiB
C++
/***
|
|
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"
|
|
|
|
#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
|
|
|
|
namespace Aurora::Debug
|
|
{
|
|
static thread_local AuString tlsLastMessageError;
|
|
static AuString strFailureCategoryCache[128];
|
|
|
|
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;
|
|
}
|
|
|
|
void SetOOM(ErrorStack *pStack)
|
|
{
|
|
pStack->bOutOfMemory = true;
|
|
}
|
|
};
|
|
|
|
AUKN_SYM const AuString &ThreadMessage::ToString()
|
|
{
|
|
if (this->pStringMessage)
|
|
{
|
|
return *this->pStringMessage;
|
|
}
|
|
|
|
if (eFailureCategory)
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (optOsErrorCode)
|
|
{
|
|
return tlsLastMessageError = fmt::format("OS = {}", (AuUInt)*optOsErrorCode);
|
|
}
|
|
|
|
return "Unknown error.";
|
|
}
|
|
|
|
static thread_local ErrorStack *tlsErrorStackBase;
|
|
|
|
AUKN_SYM ErrorStack::ErrorStack()
|
|
{
|
|
auto pStack = this;
|
|
|
|
if (!tlsErrorStackBase)
|
|
{
|
|
tlsErrorStackBase = pStack;
|
|
return;
|
|
}
|
|
|
|
ErrorStackAccessor dumb;
|
|
auto itr = tlsErrorStackBase;
|
|
while (auto pNext = dumb.GetNext(itr))
|
|
{
|
|
itr = pNext;
|
|
}
|
|
|
|
dumb.SetNext(itr, pStack);
|
|
}
|
|
|
|
AUKN_SYM ErrorStack::~ErrorStack()
|
|
{
|
|
auto pStack = this;
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
void OnOutOfMemory()
|
|
{
|
|
ErrorStackAccessor dumb;
|
|
auto itr = tlsErrorStackBase;
|
|
|
|
if (itr)
|
|
{
|
|
dumb.SetOOM(itr);
|
|
while (auto pNext = dumb.GetNext(itr))
|
|
{
|
|
dumb.SetOOM(itr);
|
|
itr = pNext;
|
|
}
|
|
}
|
|
}
|
|
} |