GBA Thread: Add functionality for running callbacks on the GBA thread

This commit is contained in:
Jeffrey Pfau 2015-04-26 14:06:57 -07:00
parent 9c07698068
commit 91ee44c458
5 changed files with 38 additions and 11 deletions

View File

@ -46,6 +46,7 @@ Misc:
- Debugger: Free watchpoints in addition to breakpoints - Debugger: Free watchpoints in addition to breakpoints
- Qt: Move GL frame drawing back onto its own thread - Qt: Move GL frame drawing back onto its own thread
- GBA: Add status log level - GBA: Add status log level
- GBA Thread: Add functionality for running callbacks on the GBA thread
0.2.0: (2015-04-03) 0.2.0: (2015-04-03)
Features: Features:

View File

@ -274,6 +274,13 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
threadContext->state = THREAD_INTERRUPTED; threadContext->state = THREAD_INTERRUPTED;
ConditionWake(&threadContext->stateCond); 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) { if (threadContext->state == THREAD_RESETING) {
threadContext->state = THREAD_RUNNING; threadContext->state = THREAD_RUNNING;
resetScheduled = 1; resetScheduled = 1;
@ -598,6 +605,17 @@ void GBAThreadContinue(struct GBAThread* threadContext) {
MutexUnlock(&threadContext->stateMutex); 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);
}
void GBAThreadPause(struct GBAThread* threadContext) { void GBAThreadPause(struct GBAThread* threadContext) {
bool frameOn = true; bool frameOn = true;
MutexLock(&threadContext->stateMutex); MutexLock(&threadContext->stateMutex);

View File

@ -28,6 +28,7 @@ enum ThreadState {
THREAD_INTERRUPTING, THREAD_INTERRUPTING,
THREAD_PAUSED, THREAD_PAUSED,
THREAD_PAUSING, THREAD_PAUSING,
THREAD_RUN_ON,
THREAD_RESETING, THREAD_RESETING,
THREAD_EXITING, THREAD_EXITING,
THREAD_SHUTDOWN, THREAD_SHUTDOWN,
@ -97,6 +98,7 @@ struct GBAThread {
ThreadCallback cleanCallback; ThreadCallback cleanCallback;
ThreadCallback frameCallback; ThreadCallback frameCallback;
void* userData; void* userData;
void (*run)(struct GBAThread*);
struct GBASync sync; struct GBASync sync;
@ -126,6 +128,8 @@ bool GBAThreadIsActive(struct GBAThread* threadContext);
void GBAThreadInterrupt(struct GBAThread* threadContext); void GBAThreadInterrupt(struct GBAThread* threadContext);
void GBAThreadContinue(struct GBAThread* threadContext); void GBAThreadContinue(struct GBAThread* threadContext);
void GBARunOnThread(struct GBAThread* threadContext, void (*run)(struct GBAThread*));
void GBAThreadPause(struct GBAThread* threadContext); void GBAThreadPause(struct GBAThread* threadContext);
void GBAThreadUnpause(struct GBAThread* threadContext); void GBAThreadUnpause(struct GBAThread* threadContext);
bool GBAThreadIsPaused(struct GBAThread* threadContext); bool GBAThreadIsPaused(struct GBAThread* threadContext);

View File

@ -506,17 +506,21 @@ void GameController::setUseBIOS(bool use) {
} }
void GameController::loadState(int slot) { void GameController::loadState(int slot) {
threadInterrupt(); m_stateSlot = slot;
GBALoadState(&m_threadContext, m_threadContext.stateDir, slot); GBARunOnThread(&m_threadContext, [](GBAThread* context) {
threadContinue(); GameController* controller = static_cast<GameController*>(context->userData);
emit stateLoaded(&m_threadContext); GBALoadState(context, context->stateDir, controller->m_stateSlot);
emit frameAvailable(m_drawContext); controller->stateLoaded(context);
controller->frameAvailable(controller->m_drawContext);
});
} }
void GameController::saveState(int slot) { void GameController::saveState(int slot) {
threadInterrupt(); m_stateSlot = slot;
GBASaveState(&m_threadContext, m_threadContext.stateDir, slot, true); GBARunOnThread(&m_threadContext, [](GBAThread* context) {
threadContinue(); GameController* controller = static_cast<GameController*>(context->userData);
GBASaveState(context, context->stateDir, controller->m_stateSlot, true);
});
} }
void GameController::setVideoSync(bool set) { void GameController::setVideoSync(bool set) {
@ -595,9 +599,7 @@ void GameController::clearAVStream() {
#ifdef USE_PNG #ifdef USE_PNG
void GameController::screenshot() { void GameController::screenshot() {
GBAThreadInterrupt(&m_threadContext); GBARunOnThread(&m_threadContext, GBAThreadTakeScreenshot);
GBAThreadTakeScreenshot(&m_threadContext);
GBAThreadContinue(&m_threadContext);
} }
#endif #endif

View File

@ -184,6 +184,8 @@ private:
bool m_turbo; bool m_turbo;
bool m_turboForced; bool m_turboForced;
int m_stateSlot;
InputController* m_inputController; InputController* m_inputController;
std::shared_ptr<MultiplayerController> m_multiplayer; std::shared_ptr<MultiplayerController> m_multiplayer;