[+] Begin expanding OSThread to offer more signals. This needs optimizing
This commit is contained in:
parent
8d0641ab00
commit
9ed6d2ff03
@ -7,32 +7,38 @@
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Loop
|
||||
{
|
||||
class ILoopSource;
|
||||
}
|
||||
|
||||
namespace Aurora::Threading::Threads
|
||||
{
|
||||
class TLSView;
|
||||
|
||||
/// 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
|
||||
{
|
||||
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.
|
||||
// release-is-always-terminate assumption.
|
||||
|
||||
virtual bool Run() = 0;
|
||||
virtual void Exit() = 0;
|
||||
@ -56,5 +62,9 @@ namespace Aurora::Threading::Threads
|
||||
|
||||
virtual void ExecuteInDeadThread(std::function<void()> callback) = 0;
|
||||
virtual AuSPtr<IWaitable> AsWaitable() = 0;
|
||||
virtual AuSPtr<Loop::ILoopSource> AsLoopSource() = 0;
|
||||
|
||||
virtual AuSPtr<IWaitable> GetShutdownSignalWaitable() = 0;
|
||||
virtual AuSPtr<Loop::ILoopSource> GetShutdownSignalLS() = 0;
|
||||
};
|
||||
}
|
@ -33,6 +33,12 @@ namespace Aurora::Threading::Threads
|
||||
{
|
||||
name_ = info.name.value_or("Aurora Thread");
|
||||
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();
|
||||
SysAssert(terminated_ ? true : false, "out of memory");
|
||||
}
|
||||
@ -97,6 +103,16 @@ namespace Aurora::Threading::Threads
|
||||
void OSThread::SendExitSignal()
|
||||
{
|
||||
exiting_ = true;
|
||||
|
||||
if (this->terminateSignalLs_)
|
||||
{
|
||||
this->terminateSignalLs_->Set();
|
||||
}
|
||||
|
||||
if (this->terminateSignal_)
|
||||
{
|
||||
this->terminateSignal_->Set();
|
||||
}
|
||||
}
|
||||
|
||||
bool OSThread::Run()
|
||||
@ -574,10 +590,16 @@ namespace Aurora::Threading::Threads
|
||||
{
|
||||
exitOnlyOnce_->Unlock();
|
||||
terminated_->Set();
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
if (terminatedSignalLs_)
|
||||
{
|
||||
terminatedSignalLs_->Set();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OSThread::TeminateOSContext(bool calledFromThis)
|
||||
{
|
||||
@ -617,4 +639,19 @@ namespace Aurora::Threading::Threads
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
AuSPtr<Loop::ILoopSource> OSThread::AsLoopSource()
|
||||
{
|
||||
return this->terminateSignalLs_;
|
||||
}
|
||||
|
||||
AuSPtr<IWaitable> OSThread::GetShutdownSignalWaitable()
|
||||
{
|
||||
return this->terminateSignal_;
|
||||
}
|
||||
|
||||
AuSPtr<Loop::ILoopSource> OSThread::GetShutdownSignalLS()
|
||||
{
|
||||
return this->terminateSignalLs_;
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,9 @@ namespace Aurora::Threading::Threads
|
||||
void AddLastHopeTlsHook(const AuSPtr<Threading::Threads::IThreadFeature> &feature) override;
|
||||
|
||||
void _ThreadEP();
|
||||
|
||||
AuSPtr<Loop::ILoopSource> AsLoopSource() override;
|
||||
AuSPtr<IWaitable> GetShutdownSignalWaitable() override;
|
||||
AuSPtr<Loop::ILoopSource> GetShutdownSignalLS() override;
|
||||
protected:
|
||||
|
||||
bool Exit(bool willReturnToOS);
|
||||
@ -66,6 +68,9 @@ namespace Aurora::Threading::Threads
|
||||
bool exiting_{};
|
||||
bool contextUsed_{}; // can this thread instance execute code again?
|
||||
Primitives::EventShared_t terminated_;
|
||||
Primitives::EventShared_t terminateSignal_;
|
||||
AuSPtr<Loop::ILSEvent> terminateSignalLs_;
|
||||
AuSPtr<Loop::ILSEvent> terminatedSignalLs_;
|
||||
|
||||
Primitives::CriticalSectionUnique_t exitOnlyOnce_;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user