GBA Thread: Make GBAThreadInterrupt and -Continue check for the thread status, resolving several deadlocks

This commit is contained in:
Jeffrey Pfau 2014-11-09 20:31:24 -08:00
parent 6e62ba8bb2
commit d83520c5a2
4 changed files with 24 additions and 27 deletions

View File

@ -426,10 +426,14 @@ void GBAThreadJoin(struct GBAThread* threadContext) {
}
}
bool GBAThreadIsActive(struct GBAThread* threadContext) {
return threadContext->state >= THREAD_RUNNING && threadContext->state < THREAD_EXITING;
}
void GBAThreadInterrupt(struct GBAThread* threadContext) {
MutexLock(&threadContext->stateMutex);
++threadContext->interruptDepth;
if (threadContext->interruptDepth > 1) {
if (threadContext->interruptDepth > 1 || !GBAThreadIsActive(threadContext)) {
MutexUnlock(&threadContext->stateMutex);
return;
}
@ -447,7 +451,7 @@ void GBAThreadInterrupt(struct GBAThread* threadContext) {
void GBAThreadContinue(struct GBAThread* threadContext) {
MutexLock(&threadContext->stateMutex);
--threadContext->interruptDepth;
if (threadContext->interruptDepth < 1) {
if (threadContext->interruptDepth < 1 && GBAThreadIsActive(threadContext)) {
threadContext->state = threadContext->savedState;
ConditionWake(&threadContext->stateCond);
}

View File

@ -104,6 +104,7 @@ void GBAThreadEnd(struct GBAThread* threadContext);
void GBAThreadReset(struct GBAThread* threadContext);
void GBAThreadJoin(struct GBAThread* threadContext);
bool GBAThreadIsActive(struct GBAThread* threadContext);
void GBAThreadInterrupt(struct GBAThread* threadContext);
void GBAThreadContinue(struct GBAThread* threadContext);

View File

@ -52,13 +52,17 @@ void Display::startDrawing(const uint32_t* buffer, GBAThread* thread) {
void Display::stopDrawing() {
if (m_drawThread) {
GBAThreadInterrupt(m_context);
GBASyncSuspendDrawing(&m_context->sync);
if (GBAThreadIsActive(m_context)) {
GBAThreadInterrupt(m_context);
GBASyncSuspendDrawing(&m_context->sync);
}
QMetaObject::invokeMethod(m_painter, "stop", Qt::BlockingQueuedConnection);
m_drawThread->exit();
m_drawThread = nullptr;
GBASyncResumeDrawing(&m_context->sync);
GBAThreadContinue(m_context);
if (GBAThreadIsActive(m_context)) {
GBASyncResumeDrawing(&m_context->sync);
GBAThreadContinue(m_context);
}
}
}

View File

@ -250,13 +250,9 @@ void GameController::setAudioBufferSamples(int samples) {
}
void GameController::setFPSTarget(float fps) {
if (m_gameOpen) {
GBAThreadInterrupt(&m_threadContext);
m_threadContext.fpsTarget = fps;
GBAThreadContinue(&m_threadContext);
} else {
m_threadContext.fpsTarget = fps;
}
GBAThreadInterrupt(&m_threadContext);
m_threadContext.fpsTarget = fps;
GBAThreadContinue(&m_threadContext);
QMetaObject::invokeMethod(m_audioProcessor, "inputParametersChanged");
}
@ -315,23 +311,15 @@ void GameController::setTurbo(bool set, bool forced) {
}
void GameController::setAVStream(GBAAVStream* stream) {
if (m_gameOpen) {
GBAThreadInterrupt(&m_threadContext);
m_threadContext.stream = stream;
GBAThreadContinue(&m_threadContext);
} else {
m_threadContext.stream = stream;
}
GBAThreadInterrupt(&m_threadContext);
m_threadContext.stream = stream;
GBAThreadContinue(&m_threadContext);
}
void GameController::clearAVStream() {
if (m_gameOpen) {
GBAThreadInterrupt(&m_threadContext);
m_threadContext.stream = nullptr;
GBAThreadContinue(&m_threadContext);
} else {
m_threadContext.stream = nullptr;
}
GBAThreadInterrupt(&m_threadContext);
m_threadContext.stream = nullptr;
GBAThreadContinue(&m_threadContext);
}
void GameController::updateKeys() {