mirror of https://github.com/mgba-emu/mgba.git
Core: Add pause/unpause callbacks to mCoreThread
This commit is contained in:
parent
1733c64561
commit
1a74924023
|
@ -34,6 +34,8 @@ struct mCoreThread {
|
||||||
ThreadCallback cleanCallback;
|
ThreadCallback cleanCallback;
|
||||||
ThreadCallback frameCallback;
|
ThreadCallback frameCallback;
|
||||||
ThreadCallback sleepCallback;
|
ThreadCallback sleepCallback;
|
||||||
|
ThreadCallback pauseCallback;
|
||||||
|
ThreadCallback unpauseCallback;
|
||||||
void* userData;
|
void* userData;
|
||||||
void (*run)(struct mCoreThread*);
|
void (*run)(struct mCoreThread*);
|
||||||
|
|
||||||
|
@ -50,13 +52,19 @@ enum mCoreThreadState {
|
||||||
THREAD_RUNNING = 0,
|
THREAD_RUNNING = 0,
|
||||||
THREAD_REWINDING,
|
THREAD_REWINDING,
|
||||||
THREAD_MAX_RUNNING = THREAD_REWINDING,
|
THREAD_MAX_RUNNING = THREAD_REWINDING,
|
||||||
|
|
||||||
|
THREAD_WAITING,
|
||||||
THREAD_INTERRUPTED,
|
THREAD_INTERRUPTED,
|
||||||
THREAD_INTERRUPTING,
|
|
||||||
THREAD_PAUSED,
|
THREAD_PAUSED,
|
||||||
|
THREAD_MAX_WAITING = THREAD_PAUSED,
|
||||||
|
|
||||||
THREAD_PAUSING,
|
THREAD_PAUSING,
|
||||||
THREAD_RUN_ON,
|
THREAD_RUN_ON,
|
||||||
THREAD_WAITING,
|
|
||||||
THREAD_RESETING,
|
THREAD_RESETING,
|
||||||
|
THREAD_MIN_DEFERRED = THREAD_PAUSING,
|
||||||
|
THREAD_MAX_DEFERRED = THREAD_RESETING,
|
||||||
|
|
||||||
|
THREAD_INTERRUPTING,
|
||||||
THREAD_EXITING,
|
THREAD_EXITING,
|
||||||
THREAD_SHUTDOWN,
|
THREAD_SHUTDOWN,
|
||||||
THREAD_CRASHED
|
THREAD_CRASHED
|
||||||
|
|
|
@ -195,38 +195,58 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int resetScheduled = 0;
|
enum mCoreThreadState deferred = THREAD_RUNNING;
|
||||||
MutexLock(&impl->stateMutex);
|
MutexLock(&impl->stateMutex);
|
||||||
while (impl->state > THREAD_MAX_RUNNING && impl->state < THREAD_EXITING) {
|
while (impl->state > THREAD_MAX_RUNNING && impl->state < THREAD_EXITING) {
|
||||||
if (impl->state == THREAD_PAUSING) {
|
deferred = impl->state;
|
||||||
impl->state = THREAD_PAUSED;
|
|
||||||
ConditionWake(&impl->stateCond);
|
|
||||||
}
|
|
||||||
if (impl->state == THREAD_INTERRUPTING) {
|
if (impl->state == THREAD_INTERRUPTING) {
|
||||||
impl->state = THREAD_INTERRUPTED;
|
impl->state = THREAD_INTERRUPTED;
|
||||||
ConditionWake(&impl->stateCond);
|
ConditionWake(&impl->stateCond);
|
||||||
}
|
}
|
||||||
if (impl->state == THREAD_RUN_ON) {
|
|
||||||
if (threadContext->run) {
|
if (impl->state == THREAD_PAUSING) {
|
||||||
threadContext->run(threadContext);
|
impl->state = THREAD_PAUSED;
|
||||||
}
|
|
||||||
impl->state = impl->savedState;
|
|
||||||
ConditionWake(&impl->stateCond);
|
|
||||||
}
|
}
|
||||||
if (impl->state == THREAD_RESETING) {
|
if (impl->state == THREAD_RESETING) {
|
||||||
impl->state = THREAD_RUNNING;
|
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);
|
ConditionWait(&impl->stateCond, &impl->stateMutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MutexUnlock(&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);
|
core->reset(core);
|
||||||
if (threadContext->resetCallback) {
|
if (threadContext->resetCallback) {
|
||||||
threadContext->resetCallback(threadContext);
|
threadContext->resetCallback(threadContext);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -109,6 +109,18 @@ CoreController::CoreController(mCore* core, QObject* parent)
|
||||||
QMetaObject::invokeMethod(controller, "stopping");
|
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) {
|
m_threadContext.logger.d.log = [](mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) {
|
||||||
mThreadLogger* logContext = reinterpret_cast<mThreadLogger*>(logger);
|
mThreadLogger* logContext = reinterpret_cast<mThreadLogger*>(logger);
|
||||||
mCoreThread* context = logContext->p;
|
mCoreThread* context = logContext->p;
|
||||||
|
@ -344,11 +356,9 @@ void CoreController::setPaused(bool paused) {
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
m_frameActions.append([this]() {
|
m_frameActions.append([this]() {
|
||||||
mCoreThreadPauseFromThread(&m_threadContext);
|
mCoreThreadPauseFromThread(&m_threadContext);
|
||||||
QMetaObject::invokeMethod(this, "paused");
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
mCoreThreadUnpause(&m_threadContext);
|
mCoreThreadUnpause(&m_threadContext);
|
||||||
emit unpaused();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue