GBA Thread: Make GBAThreadInterrupt and -Continue check for the thread status, resolving several deadlocks
Jeffrey Pfau jeffrey@endrift.com
Sun, 09 Nov 2014 20:31:24 -0800
4 files changed,
24 insertions(+),
27 deletions(-)
M
src/gba/gba-thread.c
→
src/gba/gba-thread.c
@@ -426,10 +426,14 @@ threadContext->stateDir = 0;
} } +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 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); }
M
src/gba/gba-thread.h
→
src/gba/gba-thread.h
@@ -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);
M
src/platform/qt/Display.cpp
→
src/platform/qt/Display.cpp
@@ -52,13 +52,17 @@ }
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); + } } }
M
src/platform/qt/GameController.cpp
→
src/platform/qt/GameController.cpp
@@ -250,13 +250,9 @@ QMetaObject::invokeMethod(m_audioProcessor, "setBufferSamples", Q_ARG(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::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() {