122 lines
2.9 KiB
C++
122 lines
2.9 KiB
C++
|
/***
|
||
|
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||
|
|
||
|
File: Exit.cpp
|
||
|
Date: 2022-2-5
|
||
|
Author: Reece
|
||
|
***/
|
||
|
#include <Source/RuntimeInternal.hpp>
|
||
|
#include "Exit.hpp"
|
||
|
#include <Source/Grug/Grug.hpp>
|
||
|
#include "MTWatchDog.hpp"
|
||
|
|
||
|
namespace Aurora::Exit
|
||
|
{
|
||
|
static AuThreadPrimitives::MutexUnique_t gMutex;
|
||
|
static AuList<AuTuple<AuSPtr<IExitSubscriber>, ETriggerLevel>> gTriggerSubscribers;
|
||
|
static bool gIsAppRunning {true};
|
||
|
|
||
|
static void DispatchHandlersForThread(AuThreads::IAuroraThread *pThread, ETriggerLevel level)
|
||
|
{
|
||
|
ExitInvoker invoker;
|
||
|
|
||
|
invoker.pCaller = pThread;
|
||
|
|
||
|
for (const auto &[sub, subLevel] : gTriggerSubscribers)
|
||
|
{
|
||
|
if (level == subLevel)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
sub->OnTrigger(level, &invoker);
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
// Intentionally left empty. Telemetry hooks will report, if possible.
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PostLevel(AuThreads::IAuroraThread *thread, ETriggerLevel level)
|
||
|
{
|
||
|
AU_LOCK_GUARD(gMutex);
|
||
|
|
||
|
bool isTerminate = level == ETriggerLevel::eSafeTermination;
|
||
|
bool isPreempting {};
|
||
|
|
||
|
// Prevent double eSafeTermination
|
||
|
if (isTerminate && gHasSentTerminate)
|
||
|
{
|
||
|
isPreempting = true;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
if (isTerminate || level == ETriggerLevel::eSigTerminate)
|
||
|
{
|
||
|
gIsAppRunning = false;
|
||
|
}
|
||
|
|
||
|
// ...
|
||
|
if (level == ETriggerLevel::eProblematicEvent)
|
||
|
{
|
||
|
Grug::NotifyGrugOfLogs();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Grug::GrugFlushWrites();
|
||
|
Grug::GrugFlushFlushs();
|
||
|
}
|
||
|
|
||
|
// Has already sent eSafeTermination?
|
||
|
if (isPreempting)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Dispatch
|
||
|
DispatchHandlersForThread(thread, level);
|
||
|
|
||
|
// ...
|
||
|
gHasSentTerminate |= isTerminate;
|
||
|
|
||
|
// Force exit after calling the subscribers, should the even level be eSigTerminate
|
||
|
if (level == ETriggerLevel::eSigTerminate)
|
||
|
{
|
||
|
Process::Exit(0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
AUKN_SYM bool ExitHandlerAdd(ETriggerLevel level, const AuSPtr<IExitSubscriber> &callback)
|
||
|
{
|
||
|
AU_LOCK_GUARD(gMutex);
|
||
|
|
||
|
return AuTryInsert(gTriggerSubscribers, AuMakePair(callback, level));
|
||
|
}
|
||
|
|
||
|
AUKN_SYM void ExitHandlerRemove(const AuSPtr<IExitSubscriber> &callback)
|
||
|
{
|
||
|
AU_LOCK_GUARD(gMutex);
|
||
|
|
||
|
AuRemoveAllIf(gTriggerSubscribers, [=](const auto &entry) -> bool
|
||
|
{
|
||
|
return AuGet<0>(entry) == callback;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
AUKN_SYM bool IsAppRunning()
|
||
|
{
|
||
|
return gIsAppRunning;
|
||
|
}
|
||
|
|
||
|
void InitExit()
|
||
|
{
|
||
|
gMutex = AuThreadPrimitives::MutexUnique();
|
||
|
InitWatchdog();
|
||
|
}
|
||
|
|
||
|
void DeinitExit()
|
||
|
{
|
||
|
gMutex.reset();
|
||
|
}
|
||
|
}
|