[+] Added AuroraInterface IThreadVectors for thread creation

[+] ThreadInfo's constructor now accepts additional arguments for name and stack
[*] Deprecate AbstractThreadVectors
[+] note about detaching threads
This commit is contained in:
Reece Wilson 2021-10-23 19:25:43 +01:00
parent 81abb38316
commit fe529f3dc4
7 changed files with 69 additions and 18 deletions

View File

@ -15,9 +15,15 @@ namespace Aurora::Threading::Threads
User-provided interface-style callback structure of thread related events <br> User-provided interface-style callback structure of thread related events <br>
DoRun/DoExit are called within the threads context DoRun/DoExit are called within the threads context
*/ */
/// @deprecated
struct AbstractThreadVectors struct AbstractThreadVectors
{ {
std::function<void(IAuroraThread *)> DoRun; AuConsumer<IAuroraThread *> DoRun;
std::function<void(IAuroraThread *)> DoExit; AuConsumer<IAuroraThread *> DoExit;
}; };
AUKN_INTERFACE(IThreadVectors,
AUI_METHOD(void, OnEntry, (IAuroraThread *, thread)),
AUI_METHOD(void, OnExit, (IAuroraThread *, thread))
);
} }

View File

@ -15,6 +15,25 @@ namespace Aurora::Threading::Threads
class IAuroraThread class IAuroraThread
{ {
public: public:
// TODO: consider detach support.
// It's actually really comfy that resetting/destroying the thread forces you to sync to termination
// The common/forced semantic:
// worker->SendExitSignal(); // sets the exiting flag
// DestoryThread(worker); // in the dtor, a watchdog is triggered over the shutdown of the thread
//
// WorkerMain()
// while (!this->Exiting()) {}
//
// It's Similar to Java
// -> think while (Thread.currentThread().isAlive()) { doWork() }
// -> plus you own the thread and its' execution
//
// One could always use AsWaitable() to get an event object that is triggered once the thread shuts down
// It's not like there isn't a traditional IWaitable interface support backing on thread termination
// The problem is, if the aurora runtime transfers ownership of an IAuroraThread to you, you have to leak it
// or you have to be forced to use the very comfy dtor mechanic. We need a detach function to overload this
// release is always terminate assumption.
virtual bool Run() = 0; virtual bool Run() = 0;
virtual void Exit() = 0; virtual void Exit() = 0;
virtual bool Exiting() = 0; virtual bool Exiting() = 0;

View File

@ -11,11 +11,26 @@ namespace Aurora::Threading::Threads
{ {
struct ThreadInfo struct ThreadInfo
{ {
const AbstractThreadVectors &vectors; /// @deprecated
AbstractThreadVectors vectors;
AuSPtr<IThreadVectors> callbacks;
/// @deprecated
ThreadInfo(const AbstractThreadVectors &vectors) : vectors(vectors) ThreadInfo(const AbstractThreadVectors &vectors) : vectors(vectors)
{} {}
ThreadInfo(const AuSPtr<IThreadVectors> &callbacks) : callbacks(callbacks)
{}
ThreadInfo(const AuSPtr<IThreadVectors> &callbacks, const AuString &name) : callbacks(callbacks), name(name)
{}
ThreadInfo(const AuSPtr<IThreadVectors> &callbacks, const AuString &name, AuUInt32 stackSize) : callbacks(callbacks), name(name), stackSize(stackSize)
{}
ThreadInfo(const AuSPtr<IThreadVectors> &callbacks, AuUInt32 stackSize) : callbacks(callbacks), name(name), stackSize(stackSize)
{}
AuOptional<AuUInt32> stackSize; AuOptional<AuUInt32> stackSize;
AuOptional<AuString> name; AuOptional<AuString> name;
}; };

View File

@ -30,9 +30,8 @@ namespace Aurora::Threading::Threads
static AbstractThreadVectors gDummyVectors {}; static AbstractThreadVectors gDummyVectors {};
static ThreadInfo gDummyThreadInfo(gDummyVectors); static ThreadInfo gDummyThreadInfo(gDummyVectors);
OSThread::OSThread(const ThreadInfo &info) : info_(vecs) OSThread::OSThread(const ThreadInfo &info) : info_(info)
{ {
vecs = info.vectors;
info_.stackSize = info.stackSize; info_.stackSize = info.stackSize;
info_.name = info.name; info_.name = info.name;
name_ = info.name.value_or("Aurora Thread"); name_ = info.name.value_or("Aurora Thread");
@ -121,10 +120,15 @@ namespace Aurora::Threading::Threads
{ {
try try
{ {
// this functional backends are being deprecated
if (info_.vectors.DoRun) if (info_.vectors.DoRun)
{ {
info_.vectors.DoRun(this); info_.vectors.DoRun(this);
} }
else if (info_.callbacks)
{
info_.callbacks->OnEntry(this);
}
} }
catch (...) catch (...)
{ {
@ -553,23 +557,27 @@ namespace Aurora::Threading::Threads
HookOnExit(); HookOnExit();
// dispatch kill callback try
if (info_.vectors.DoExit)
{ {
try // dispatch kill callback
if (info_.vectors.DoExit)
{ {
info_.vectors.DoExit(this); info_.vectors.DoExit(this);
} }
catch (...) else if (info_.callbacks)
{ {
Debug::PrintError(); info_.callbacks->OnExit(this);
LogWarn("Couldn't deinitialize thread");
LogWarn("The smart thing to do at this point would be to panic");
LogWarn("...but we could continue");
LogWarn("Carrying on despite the potential for data integrity loss and memory leaks");
Telemetry::Mayday();
} }
} }
catch (...)
{
Debug::PrintError();
LogWarn("Couldn't deinitialize thread");
LogWarn("The smart thing to do at this point would be to panic");
LogWarn("...but we could continue");
LogWarn("Carrying on despite the potential for data integrity loss and memory leaks");
Telemetry::Mayday();
}
HookReleaseThreadResources(); HookReleaseThreadResources();

View File

@ -59,7 +59,6 @@ namespace Aurora::Threading::Threads
Primitives::SpinLock tlsLock_; Primitives::SpinLock tlsLock_;
AuSPtr<TLSView> tls_; AuSPtr<TLSView> tls_;
AuString name_; AuString name_;
AbstractThreadVectors vecs;
ThreadInfo info_; ThreadInfo info_;
AuUInt32 affinityProcessMask_ = 0xFFFFFFFF; AuUInt32 affinityProcessMask_ = 0xFFFFFFFF;
EThreadPrio prio_ = EThreadPrio::ePrioNormal; EThreadPrio prio_ = EThreadPrio::ePrioNormal;

View File

@ -87,7 +87,10 @@ namespace Aurora::Threading::Threads
void OsThreadShutdown(AuUInt64 threadId) void OsThreadShutdown(AuUInt64 threadId)
{ {
SysAssertDbg(tlsOsFallbackThread.threadId == threadId); SysAssertDbg(tlsOsFallbackThread.threadId == threadId);
SafeDelete<OSThread *>(tlsOsFallbackThread.handle); if (tlsOsFallbackThread.handle)
{
SafeDelete<OSThread *>(tlsOsFallbackThread.handle);
}
} }
AUKN_SYM IAuroraThread *GetThread() AUKN_SYM IAuroraThread *GetThread()

View File

@ -13,6 +13,7 @@ namespace Aurora::Threading::Threads
{ {
AUKN_SYM IAuroraThread *ThreadNew(const ThreadInfo &info) AUKN_SYM IAuroraThread *ThreadNew(const ThreadInfo &info)
{ {
if (!info.callbacks && !(info.vectors.DoRun)) return {};
return _new OSThread(info); return _new OSThread(info);
} }