[+] Begin expanding OSThread to offer more signals. This needs optimizing

This commit is contained in:
Reece Wilson 2021-10-25 18:08:28 +01:00
parent 8d0641ab00
commit 9ed6d2ff03
3 changed files with 69 additions and 17 deletions

View File

@ -7,32 +7,38 @@
***/ ***/
#pragma once #pragma once
namespace Aurora::Loop
{
class ILoopSource;
}
namespace Aurora::Threading::Threads namespace Aurora::Threading::Threads
{ {
class TLSView; class TLSView;
/// Threads may be reimplemented as fibers or under some other userland context switcher /// Threads may be reimplemented as fibers or under some other userland context switcher
/// IAuroraThread objects when unique ownership is passed to you maintain ownership of the execution
/// Once you release your final reference to the IAuroraThread, the exit flag is set, the termination
/// signals are sent, and a watchdog watches over the termination of the thread.
///
/// A common worker thread semantic:
/// EndWorker()
/// m_Worker->SendExitSignal(); // sets the exiting flag
/// DestroyThread(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
class IAuroraThread class IAuroraThread
{ {
public: public:
// TODO: consider detach support. // 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 // 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 // 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. // release-is-always-terminate assumption.
virtual bool Run() = 0; virtual bool Run() = 0;
virtual void Exit() = 0; virtual void Exit() = 0;
@ -56,5 +62,9 @@ namespace Aurora::Threading::Threads
virtual void ExecuteInDeadThread(std::function<void()> callback) = 0; virtual void ExecuteInDeadThread(std::function<void()> callback) = 0;
virtual AuSPtr<IWaitable> AsWaitable() = 0; virtual AuSPtr<IWaitable> AsWaitable() = 0;
virtual AuSPtr<Loop::ILoopSource> AsLoopSource() = 0;
virtual AuSPtr<IWaitable> GetShutdownSignalWaitable() = 0;
virtual AuSPtr<Loop::ILoopSource> GetShutdownSignalLS() = 0;
}; };
} }

View File

@ -33,6 +33,12 @@ namespace Aurora::Threading::Threads
{ {
name_ = info.name.value_or("Aurora Thread"); name_ = info.name.value_or("Aurora Thread");
terminated_ = Primitives::EventShared(true, false); terminated_ = Primitives::EventShared(true, false);
// maybe we should atomic exchange compare these when needed frogthink
terminateSignal_ = Primitives::EventShared(true, false, true);
terminatedSignalLs_ = Loop::NewLSEvent(true, false);
terminateSignalLs_ = Loop::NewLSEvent(true, false, true);
exitOnlyOnce_ = Primitives::CriticalSectionUnique(); exitOnlyOnce_ = Primitives::CriticalSectionUnique();
SysAssert(terminated_ ? true : false, "out of memory"); SysAssert(terminated_ ? true : false, "out of memory");
} }
@ -97,6 +103,16 @@ namespace Aurora::Threading::Threads
void OSThread::SendExitSignal() void OSThread::SendExitSignal()
{ {
exiting_ = true; exiting_ = true;
if (this->terminateSignalLs_)
{
this->terminateSignalLs_->Set();
}
if (this->terminateSignal_)
{
this->terminateSignal_->Set();
}
} }
bool OSThread::Run() bool OSThread::Run()
@ -574,11 +590,17 @@ namespace Aurora::Threading::Threads
{ {
exitOnlyOnce_->Unlock(); exitOnlyOnce_->Unlock();
terminated_->Set(); terminated_->Set();
}
if (terminatedSignalLs_)
{
terminatedSignalLs_->Set();
} }
return true; return true;
} }
void OSThread::TeminateOSContext(bool calledFromThis) void OSThread::TeminateOSContext(bool calledFromThis)
{ {
#if defined(AURORA_IS_MODERNNT_DERIVED) #if defined(AURORA_IS_MODERNNT_DERIVED)
@ -617,4 +639,19 @@ namespace Aurora::Threading::Threads
} }
#endif #endif
} }
AuSPtr<Loop::ILoopSource> OSThread::AsLoopSource()
{
return this->terminateSignalLs_;
}
AuSPtr<IWaitable> OSThread::GetShutdownSignalWaitable()
{
return this->terminateSignal_;
}
AuSPtr<Loop::ILoopSource> OSThread::GetShutdownSignalLS()
{
return this->terminateSignalLs_;
}
} }

View File

@ -38,7 +38,9 @@ namespace Aurora::Threading::Threads
void AddLastHopeTlsHook(const AuSPtr<Threading::Threads::IThreadFeature> &feature) override; void AddLastHopeTlsHook(const AuSPtr<Threading::Threads::IThreadFeature> &feature) override;
void _ThreadEP(); void _ThreadEP();
AuSPtr<Loop::ILoopSource> AsLoopSource() override;
AuSPtr<IWaitable> GetShutdownSignalWaitable() override;
AuSPtr<Loop::ILoopSource> GetShutdownSignalLS() override;
protected: protected:
bool Exit(bool willReturnToOS); bool Exit(bool willReturnToOS);
@ -66,6 +68,9 @@ namespace Aurora::Threading::Threads
bool exiting_{}; bool exiting_{};
bool contextUsed_{}; // can this thread instance execute code again? bool contextUsed_{}; // can this thread instance execute code again?
Primitives::EventShared_t terminated_; Primitives::EventShared_t terminated_;
Primitives::EventShared_t terminateSignal_;
AuSPtr<Loop::ILSEvent> terminateSignalLs_;
AuSPtr<Loop::ILSEvent> terminatedSignalLs_;
Primitives::CriticalSectionUnique_t exitOnlyOnce_; Primitives::CriticalSectionUnique_t exitOnlyOnce_;