GBA Thread: Add functionality for running callbacks on the GBA thread
Jeffrey Pfau jeffrey@endrift.com
Sun, 26 Apr 2015 14:06:57 -0700
5 files changed,
38 insertions(+),
11 deletions(-)
M
CHANGES
→
CHANGES
@@ -46,6 +46,7 @@ - Qt: Handle saving input settings better
- Debugger: Free watchpoints in addition to breakpoints - Qt: Move GL frame drawing back onto its own thread - GBA: Add status log level + - GBA Thread: Add functionality for running callbacks on the GBA thread 0.2.0: (2015-04-03) Features:
M
src/gba/supervisor/thread.c
→
src/gba/supervisor/thread.c
@@ -274,6 +274,13 @@ if (threadContext->state == THREAD_INTERRUPTING) {
threadContext->state = THREAD_INTERRUPTED; ConditionWake(&threadContext->stateCond); } + if (threadContext->state == THREAD_RUN_ON) { + if (threadContext->run) { + threadContext->run(threadContext); + } + threadContext->state = THREAD_RUNNING; + ConditionWake(&threadContext->stateCond); + } if (threadContext->state == THREAD_RESETING) { threadContext->state = THREAD_RUNNING; resetScheduled = 1;@@ -595,6 +602,17 @@ if (threadContext->interruptDepth < 1 && GBAThreadIsActive(threadContext)) {
threadContext->state = threadContext->savedState; ConditionWake(&threadContext->stateCond); } + MutexUnlock(&threadContext->stateMutex); +} + +void GBARunOnThread(struct GBAThread* threadContext, void (*run)(struct GBAThread*)) { + MutexLock(&threadContext->stateMutex); + threadContext->run = run; + _waitOnInterrupt(threadContext); + threadContext->state = THREAD_RUN_ON; + threadContext->gba->cpu->nextEvent = 0; + ConditionWake(&threadContext->stateCond); + _waitUntilNotState(threadContext, THREAD_RUN_ON); MutexUnlock(&threadContext->stateMutex); }
M
src/gba/supervisor/thread.h
→
src/gba/supervisor/thread.h
@@ -28,6 +28,7 @@ THREAD_INTERRUPTED,
THREAD_INTERRUPTING, THREAD_PAUSED, THREAD_PAUSING, + THREAD_RUN_ON, THREAD_RESETING, THREAD_EXITING, THREAD_SHUTDOWN,@@ -97,6 +98,7 @@ ThreadCallback startCallback;
ThreadCallback cleanCallback; ThreadCallback frameCallback; void* userData; + void (*run)(struct GBAThread*); struct GBASync sync;@@ -125,6 +127,8 @@
bool GBAThreadIsActive(struct GBAThread* threadContext); void GBAThreadInterrupt(struct GBAThread* threadContext); void GBAThreadContinue(struct GBAThread* threadContext); + +void GBARunOnThread(struct GBAThread* threadContext, void (*run)(struct GBAThread*)); void GBAThreadPause(struct GBAThread* threadContext); void GBAThreadUnpause(struct GBAThread* threadContext);
M
src/platform/qt/GameController.cpp
→
src/platform/qt/GameController.cpp
@@ -506,17 +506,21 @@ threadContinue();
} void GameController::loadState(int slot) { - threadInterrupt(); - GBALoadState(&m_threadContext, m_threadContext.stateDir, slot); - threadContinue(); - emit stateLoaded(&m_threadContext); - emit frameAvailable(m_drawContext); + m_stateSlot = slot; + GBARunOnThread(&m_threadContext, [](GBAThread* context) { + GameController* controller = static_cast<GameController*>(context->userData); + GBALoadState(context, context->stateDir, controller->m_stateSlot); + controller->stateLoaded(context); + controller->frameAvailable(controller->m_drawContext); + }); } void GameController::saveState(int slot) { - threadInterrupt(); - GBASaveState(&m_threadContext, m_threadContext.stateDir, slot, true); - threadContinue(); + m_stateSlot = slot; + GBARunOnThread(&m_threadContext, [](GBAThread* context) { + GameController* controller = static_cast<GameController*>(context->userData); + GBASaveState(context, context->stateDir, controller->m_stateSlot, true); + }); } void GameController::setVideoSync(bool set) {@@ -595,9 +599,7 @@ }
#ifdef USE_PNG void GameController::screenshot() { - GBAThreadInterrupt(&m_threadContext); - GBAThreadTakeScreenshot(&m_threadContext); - GBAThreadContinue(&m_threadContext); + GBARunOnThread(&m_threadContext, GBAThreadTakeScreenshot); } #endif
M
src/platform/qt/GameController.h
→
src/platform/qt/GameController.h
@@ -184,6 +184,8 @@ bool m_audioSync;
bool m_turbo; bool m_turboForced; + int m_stateSlot; + InputController* m_inputController; std::shared_ptr<MultiplayerController> m_multiplayer;