[+] 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
|
#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;
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -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_;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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_;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user