threads now end cleanly, and do so on exit

This commit is contained in:
zetaPRIME 2017-05-03 04:19:30 -04:00
parent 88d640f3e7
commit 5577b5a6a8
4 changed files with 36 additions and 4 deletions

View File

@ -17,6 +17,9 @@ using starlight::ThemeManager;
using starlight::InputManager; using starlight::InputManager;
using starlight::gfx::RenderCore; using starlight::gfx::RenderCore;
using starlight::threading::Thread;
using starlight::threading::ThreadState;
using starlight::ui::TouchScreenCanvas; using starlight::ui::TouchScreenCanvas;
using starlight::ui::TopScreenCanvas; using starlight::ui::TopScreenCanvas;
@ -83,6 +86,9 @@ void Application::_init() {
void Application::_end() { void Application::_end() {
End(); End();
for (auto& thread : threads) thread->Exit();
threads.clear();
//for (auto& f : forms) f->Close(); //for (auto& f : forms) f->Close();
forms.clear(); // not sure why, but not doing this results in a data abort if any forms are active forms.clear(); // not sure why, but not doing this results in a data abort if any forms are active
@ -159,8 +165,10 @@ void Application::_mainLoop() {
RenderCore::EndFrame(); RenderCore::EndFrame();
while (!threads.empty() && frameTimer.GetSubframe() < 0.9) { while (!threads.empty() && frameTimer.GetSubframe() < 0.9) {
threads.front()->Resume(); auto thread = threads.front();
if (threads.size() > 1) threads.splice(threads.end(), threads, threads.begin()); // move to back of queue thread->Resume();
if (thread->state != ThreadState::Finished) threads.splice(threads.end(), threads, threads.begin()); // move to back of queue
else threads.pop_front(); // or just discard if already exited
} }
} }

View File

@ -37,6 +37,9 @@ void Thread::_FinishStart() {
state = ThreadState::Running; state = ThreadState::Running;
Yield(); Yield();
Body(); Body();
state = ThreadState::Finished;
OnExit();
threadExit(0);
} }
void Thread::Yield() { void Thread::Yield() {
@ -45,12 +48,30 @@ void Thread::Yield() {
svcWaitSynchronization(event, -1 /*U64_MAX*/); svcWaitSynchronization(event, -1 /*U64_MAX*/);
//svcWaitSynchronization(event, 65536); //svcWaitSynchronization(event, 65536);
svcClearEvent(event); svcClearEvent(event);
if (state == ThreadState::Finished && OnExit()) {
threadExit(0);
}
state = ThreadState::Running; state = ThreadState::Running;
} }
void Thread::Exit() {
if (state == ThreadState::Idle) { // exited from outside
state = ThreadState::Finished;
Resume();
threadJoin(static_cast<SysThread>(sthread), -1);
} else if (state == ThreadState::Running) { // exited self
state = ThreadState::Finished;
OnExit();
threadExit(0);
}
}
void Thread::Resume() { void Thread::Resume() {
if (state != ThreadState::Idle) return; // not applicable if (state != ThreadState::Idle && state != ThreadState::Finished) return; // not applicable
svcSignalEvent(event); svcSignalEvent(event);
} }
bool Thread::OnExit() { return true; } // default to "trivial" (no cleanup necessary)
// //

View File

@ -30,8 +30,10 @@ namespace starlight {
void Enqueue(); void Enqueue();
void Yield(); void Yield();
void Resume(); void Resume();
void Exit();
virtual void Body() = 0; virtual void Body() = 0;
virtual bool OnExit();
}; };
} }
} }

View File

@ -25,7 +25,8 @@ roadmap to v0.5.1 {
...and some mechanism for allowing it to opt out of the rest of the cycle ...and some mechanism for allowing it to opt out of the rest of the cycle
Trackable sideclass for threads; float progress 0..1, etc. Trackable sideclass for threads; float progress 0..1, etc.
MAKE THREADS END CLEANLY - MAKE THREADS END CLEANLY
^ observed a single instance of being stalled on redscreen, not really sure what that was about
} }
} then by v0.5.5 { } then by v0.5.5 {
event propagation system of some sort; threadsafe to whatever extent is needed on 3DS event propagation system of some sort; threadsafe to whatever extent is needed on 3DS