Core: Add pause/unpause callbacks to mCoreThread
Vicki Pfau vi@endrift.com
Thu, 03 Aug 2017 23:56:44 -0700
3 files changed,
56 insertions(+),
18 deletions(-)
M
include/mgba/core/thread.h
→
include/mgba/core/thread.h
@@ -34,6 +34,8 @@ ThreadCallback resetCallback;
ThreadCallback cleanCallback; ThreadCallback frameCallback; ThreadCallback sleepCallback; + ThreadCallback pauseCallback; + ThreadCallback unpauseCallback; void* userData; void (*run)(struct mCoreThread*);@@ -50,13 +52,19 @@ THREAD_INITIALIZED = -1,
THREAD_RUNNING = 0, THREAD_REWINDING, THREAD_MAX_RUNNING = THREAD_REWINDING, + + THREAD_WAITING, THREAD_INTERRUPTED, - THREAD_INTERRUPTING, THREAD_PAUSED, + THREAD_MAX_WAITING = THREAD_PAUSED, + THREAD_PAUSING, THREAD_RUN_ON, - THREAD_WAITING, THREAD_RESETING, + THREAD_MIN_DEFERRED = THREAD_PAUSING, + THREAD_MAX_DEFERRED = THREAD_RESETING, + + THREAD_INTERRUPTING, THREAD_EXITING, THREAD_SHUTDOWN, THREAD_CRASHED
M
src/core/thread.c
→
src/core/thread.c
@@ -195,38 +195,58 @@ core->runLoop(core);
} } - int resetScheduled = 0; + enum mCoreThreadState deferred = THREAD_RUNNING; MutexLock(&impl->stateMutex); while (impl->state > THREAD_MAX_RUNNING && impl->state < THREAD_EXITING) { - if (impl->state == THREAD_PAUSING) { - impl->state = THREAD_PAUSED; - ConditionWake(&impl->stateCond); - } + deferred = impl->state; + if (impl->state == THREAD_INTERRUPTING) { impl->state = THREAD_INTERRUPTED; ConditionWake(&impl->stateCond); } - if (impl->state == THREAD_RUN_ON) { - if (threadContext->run) { - threadContext->run(threadContext); - } - impl->state = impl->savedState; - ConditionWake(&impl->stateCond); + + if (impl->state == THREAD_PAUSING) { + impl->state = THREAD_PAUSED; } if (impl->state == THREAD_RESETING) { impl->state = THREAD_RUNNING; - resetScheduled = 1; } - while (impl->state == THREAD_PAUSED || impl->state == THREAD_INTERRUPTED || impl->state == THREAD_WAITING) { + + if (deferred >= THREAD_MIN_DEFERRED && deferred <= THREAD_MAX_DEFERRED) { + break; + } + + deferred = impl->state; + while (impl->state >= THREAD_WAITING && impl->state <= THREAD_MAX_WAITING) { ConditionWait(&impl->stateCond, &impl->stateMutex); } } MutexUnlock(&impl->stateMutex); - if (resetScheduled) { + switch (deferred) { + case THREAD_PAUSING: + if (threadContext->pauseCallback) { + threadContext->pauseCallback(threadContext); + } + break; + case THREAD_PAUSED: + if (threadContext->unpauseCallback) { + threadContext->unpauseCallback(threadContext); + } + break; + case THREAD_RUN_ON: + if (threadContext->run) { + threadContext->run(threadContext); + } + threadContext->impl->state = threadContext->impl->savedState; + break; + case THREAD_RESETING: core->reset(core); if (threadContext->resetCallback) { threadContext->resetCallback(threadContext); } + break; + default: + break; } }
M
src/platform/qt/CoreController.cpp
→
src/platform/qt/CoreController.cpp
@@ -109,6 +109,18 @@ controller->clearMultiplayerController();
QMetaObject::invokeMethod(controller, "stopping"); }; + m_threadContext.pauseCallback = [](mCoreThread* context) { + CoreController* controller = static_cast<CoreController*>(context->userData); + + QMetaObject::invokeMethod(controller, "paused"); + }; + + m_threadContext.unpauseCallback = [](mCoreThread* context) { + CoreController* controller = static_cast<CoreController*>(context->userData); + + QMetaObject::invokeMethod(controller, "unpaused"); + }; + m_threadContext.logger.d.log = [](mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) { mThreadLogger* logContext = reinterpret_cast<mThreadLogger*>(logger); mCoreThread* context = logContext->p;@@ -344,11 +356,9 @@ if (paused) {
QMutexLocker locker(&m_mutex); m_frameActions.append([this]() { mCoreThreadPauseFromThread(&m_threadContext); - QMetaObject::invokeMethod(this, "paused"); }); } else { mCoreThreadUnpause(&m_threadContext); - emit unpaused(); } }