forked from Mirror/libstarlight
threads now end cleanly, and do so on exit
This commit is contained in:
parent
88d640f3e7
commit
5577b5a6a8
@ -17,6 +17,9 @@ using starlight::ThemeManager;
|
||||
using starlight::InputManager;
|
||||
using starlight::gfx::RenderCore;
|
||||
|
||||
using starlight::threading::Thread;
|
||||
using starlight::threading::ThreadState;
|
||||
|
||||
using starlight::ui::TouchScreenCanvas;
|
||||
using starlight::ui::TopScreenCanvas;
|
||||
|
||||
@ -83,6 +86,9 @@ void Application::_init() {
|
||||
void Application::_end() {
|
||||
End();
|
||||
|
||||
for (auto& thread : threads) thread->Exit();
|
||||
threads.clear();
|
||||
|
||||
//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
|
||||
|
||||
@ -159,8 +165,10 @@ void Application::_mainLoop() {
|
||||
RenderCore::EndFrame();
|
||||
|
||||
while (!threads.empty() && frameTimer.GetSubframe() < 0.9) {
|
||||
threads.front()->Resume();
|
||||
if (threads.size() > 1) threads.splice(threads.end(), threads, threads.begin()); // move to back of queue
|
||||
auto thread = threads.front();
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,9 @@ void Thread::_FinishStart() {
|
||||
state = ThreadState::Running;
|
||||
Yield();
|
||||
Body();
|
||||
state = ThreadState::Finished;
|
||||
OnExit();
|
||||
threadExit(0);
|
||||
}
|
||||
|
||||
void Thread::Yield() {
|
||||
@ -45,12 +48,30 @@ void Thread::Yield() {
|
||||
svcWaitSynchronization(event, -1 /*U64_MAX*/);
|
||||
//svcWaitSynchronization(event, 65536);
|
||||
svcClearEvent(event);
|
||||
if (state == ThreadState::Finished && OnExit()) {
|
||||
threadExit(0);
|
||||
}
|
||||
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() {
|
||||
if (state != ThreadState::Idle) return; // not applicable
|
||||
if (state != ThreadState::Idle && state != ThreadState::Finished) return; // not applicable
|
||||
svcSignalEvent(event);
|
||||
}
|
||||
|
||||
bool Thread::OnExit() { return true; } // default to "trivial" (no cleanup necessary)
|
||||
|
||||
//
|
||||
|
@ -30,8 +30,10 @@ namespace starlight {
|
||||
void Enqueue();
|
||||
void Yield();
|
||||
void Resume();
|
||||
void Exit();
|
||||
|
||||
virtual void Body() = 0;
|
||||
virtual bool OnExit();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,8 @@ roadmap to v0.5.1 {
|
||||
...and some mechanism for allowing it to opt out of the rest of the cycle
|
||||
|
||||
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 {
|
||||
event propagation system of some sort; threadsafe to whatever extent is needed on 3DS
|
||||
|
Loading…
x
Reference in New Issue
Block a user