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
- 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:

View File

@ -274,6 +274,13 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
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;
@ -598,6 +605,17 @@ void GBAThreadContinue(struct GBAThread* threadContext) {
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) {
bool frameOn = true;
MutexLock(&threadContext->stateMutex);

View File

@ -28,6 +28,7 @@ enum ThreadState {
THREAD_INTERRUPTING,
THREAD_PAUSED,
THREAD_PAUSING,
THREAD_RUN_ON,
THREAD_RESETING,
THREAD_EXITING,
THREAD_SHUTDOWN,
@ -97,6 +98,7 @@ struct GBAThread {
ThreadCallback cleanCallback;
ThreadCallback frameCallback;
void* userData;
void (*run)(struct GBAThread*);
struct GBASync sync;
@ -126,6 +128,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);
bool GBAThreadIsPaused(struct GBAThread* threadContext);

View File

@ -506,17 +506,21 @@ void GameController::setUseBIOS(bool use) {
}
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 @@ void GameController::clearAVStream() {
#ifdef USE_PNG
void GameController::screenshot() {
GBAThreadInterrupt(&m_threadContext);
GBAThreadTakeScreenshot(&m_threadContext);
GBAThreadContinue(&m_threadContext);
GBARunOnThread(&m_threadContext, GBAThreadTakeScreenshot);
}
#endif

View File

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