diff --git a/libstarlight/source/starlight/threading/Thread.cpp b/libstarlight/source/starlight/threading/Thread.cpp new file mode 100644 index 0000000..e949c89 --- /dev/null +++ b/libstarlight/source/starlight/threading/Thread.cpp @@ -0,0 +1,43 @@ +#include "Thread.h" + +#include "3ds.h" + +using starlight::threading::Thread; +using SysThread = ::Thread; + +namespace { + void _ThreadEnter(void* arg) { + // cast to thread and start up + static_cast(arg)->_FinishStart(); + } +} + +Thread::~Thread() { + // ...threadjoin? something like that?? + if (event != 0) svcCloseHandle(event); +} + +void Thread::Start() { + svcCreateEvent(&event, RESET_ONESHOT); + sthread = static_cast(threadCreate(_ThreadEnter, static_cast(this), 4*1024, 0x3F, -2, false)); + +} +void Thread::_FinishStart() { + // lock out once already done + if (state != ThreadState::Init) return; + Yield(); + Body(); +} + +void Thread::Yield() { + if (state != ThreadState::Running) return; // not executing this right now, this would just futz it up + svcWaitSynchronization(event, -1 /*U64_MAX*/); + svcClearEvent(event); +} + +void Thread::Resume() { + if (state != ThreadState::Idle) return; // not applicable + svcSignalEvent(event); +} + +// diff --git a/libstarlight/source/starlight/threading/Thread.h b/libstarlight/source/starlight/threading/Thread.h new file mode 100644 index 0000000..67d464e --- /dev/null +++ b/libstarlight/source/starlight/threading/Thread.h @@ -0,0 +1,31 @@ +#pragma once +#include "starlight/_global.h" + +namespace starlight { + namespace threading { + enum class ThreadState : unsigned char { + Unqueued, Init, Idle, Running + }; + + class Thread { + protected: + volatile ThreadState state; + void* sthread; + long unsigned int event = 0; + + void Start(); + public: + ~Thread(); + + inline ThreadState State() { return state; } + + void _FinishStart(); + + void Enqueue(); + void Yield(); + void Resume(); + + virtual void Body() = 0; + }; + } +} diff --git a/libstarlight/todo.txt b/libstarlight/todo.txt index 9113d4b..b0c9acd 100644 --- a/libstarlight/todo.txt +++ b/libstarlight/todo.txt @@ -13,7 +13,7 @@ roadmap to v0.5.1 { proper thread dispatch? { Application main loop keeps a libctru TickCounter and keeps track of frame time; thread objects are held in a std::list, Application dispatches resume events and splice()s them to the end until frame time reaches some proportion of 1/60s - thread gets a yield function that calls svcWaitSynchronization on its resume event + - thread gets a yield function that calls svcWaitSynchronization on its resume event ...and some mechanism for allowing it to opt out of the rest of the cycle } } then consider these before 1.0 "gold" {