diff options
| author | Stenzek <stenzek@gmail.com> | 2019-06-29 18:25:04 +1000 |
|---|---|---|
| committer | Stenzek <stenzek@gmail.com> | 2019-07-24 04:08:25 +1000 |
| commit | a25a4e07083d4e20b5be6192892c346c4549ed73 (patch) | |
| tree | 2228eaeba0ab44e4e798fe422aa094961fd23167 /Source/Core | |
| parent | df45e714a3e7a112e53a79e4b7362c4f8aed84d5 (diff) | |
State: Use RunOnCPUThread to invoke save state handlers
This ensures that the emulated state is only touched by the CPU thread
Diffstat (limited to 'Source/Core')
| -rw-r--r-- | Source/Core/Core/State.cpp | 230 |
1 files changed, 119 insertions, 111 deletions
diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index 42a2fa792b..ed72c57128 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -204,27 +204,31 @@ void LoadFromBuffer(std::vector<u8>& buffer) return; } - Core::RunAsCPUThread([&] { - u8* ptr = &buffer[0]; - PointerWrap p(&ptr, PointerWrap::MODE_READ); - DoState(p); - }); + Core::RunOnCPUThread( + [&] { + u8* ptr = &buffer[0]; + PointerWrap p(&ptr, PointerWrap::MODE_READ); + DoState(p); + }, + true); } void SaveToBuffer(std::vector<u8>& buffer) { - Core::RunAsCPUThread([&] { - u8* ptr = nullptr; - PointerWrap p(&ptr, PointerWrap::MODE_MEASURE); - - DoState(p); - const size_t buffer_size = reinterpret_cast<size_t>(ptr); - buffer.resize(buffer_size); - - ptr = &buffer[0]; - p.SetMode(PointerWrap::MODE_WRITE); - DoState(p); - }); + Core::RunOnCPUThread( + [&] { + u8* ptr = nullptr; + PointerWrap p(&ptr, PointerWrap::MODE_MEASURE); + + DoState(p); + const size_t buffer_size = reinterpret_cast<size_t>(ptr); + buffer.resize(buffer_size); + + ptr = &buffer[0]; + p.SetMode(PointerWrap::MODE_WRITE); + DoState(p); + }, + true); } // return state number not in map @@ -381,42 +385,44 @@ static void CompressAndDumpState(CompressAndDumpState_args save_args) void SaveAs(const std::string& filename, bool wait) { - Core::RunAsCPUThread([&] { - // Measure the size of the buffer. - u8* ptr = nullptr; - PointerWrap p(&ptr, PointerWrap::MODE_MEASURE); - DoState(p); - const size_t buffer_size = reinterpret_cast<size_t>(ptr); - - // Then actually do the write. - { - std::lock_guard<std::mutex> lk(g_cs_current_buffer); - g_current_buffer.resize(buffer_size); - ptr = &g_current_buffer[0]; - p.SetMode(PointerWrap::MODE_WRITE); - DoState(p); - } - - if (p.GetMode() == PointerWrap::MODE_WRITE) - { - Core::DisplayMessage("Saving State...", 1000); - - CompressAndDumpState_args save_args; - save_args.buffer_vector = &g_current_buffer; - save_args.buffer_mutex = &g_cs_current_buffer; - save_args.filename = filename; - save_args.wait = wait; - - Flush(); - g_save_thread = std::thread(CompressAndDumpState, save_args); - g_compressAndDumpStateSyncEvent.Wait(); - } - else - { - // someone aborted the save by changing the mode? - Core::DisplayMessage("Unable to save: Internal DoState Error", 4000); - } - }); + Core::RunOnCPUThread( + [&] { + // Measure the size of the buffer. + u8* ptr = nullptr; + PointerWrap p(&ptr, PointerWrap::MODE_MEASURE); + DoState(p); + const size_t buffer_size = reinterpret_cast<size_t>(ptr); + + // Then actually do the write. + { + std::lock_guard<std::mutex> lk(g_cs_current_buffer); + g_current_buffer.resize(buffer_size); + ptr = &g_current_buffer[0]; + p.SetMode(PointerWrap::MODE_WRITE); + DoState(p); + } + + if (p.GetMode() == PointerWrap::MODE_WRITE) + { + Core::DisplayMessage("Saving State...", 1000); + + CompressAndDumpState_args save_args; + save_args.buffer_vector = &g_current_buffer; + save_args.buffer_mutex = &g_cs_current_buffer; + save_args.filename = filename; + save_args.wait = wait; + + Flush(); + g_save_thread = std::thread(CompressAndDumpState, save_args); + g_compressAndDumpStateSyncEvent.Wait(); + } + else + { + // someone aborted the save by changing the mode? + Core::DisplayMessage("Unable to save: Internal DoState Error", 4000); + } + }, + true); } bool ReadHeader(const std::string& filename, StateHeader& header) @@ -525,64 +531,66 @@ void LoadAs(const std::string& filename) return; } - Core::RunAsCPUThread([&] { - g_loadDepth++; - - // Save temp buffer for undo load state - if (!Movie::IsJustStartingRecordingInputFromSaveState()) - { - std::lock_guard<std::mutex> lk(g_cs_undo_load_buffer); - SaveToBuffer(g_undo_load_buffer); - if (Movie::IsMovieActive()) - Movie::SaveRecording(File::GetUserPath(D_STATESAVES_IDX) + "undo.dtm"); - else if (File::Exists(File::GetUserPath(D_STATESAVES_IDX) + "undo.dtm")) - File::Delete(File::GetUserPath(D_STATESAVES_IDX) + "undo.dtm"); - } - - bool loaded = false; - bool loadedSuccessfully = false; - - // brackets here are so buffer gets freed ASAP - { - std::vector<u8> buffer; - LoadFileStateData(filename, buffer); - - if (!buffer.empty()) - { - u8* ptr = &buffer[0]; - PointerWrap p(&ptr, PointerWrap::MODE_READ); - DoState(p); - loaded = true; - loadedSuccessfully = (p.GetMode() == PointerWrap::MODE_READ); - } - } - - if (loaded) - { - if (loadedSuccessfully) - { - Core::DisplayMessage(StringFromFormat("Loaded state from %s", filename.c_str()), 2000); - if (File::Exists(filename + ".dtm")) - Movie::LoadInput(filename + ".dtm"); - else if (!Movie::IsJustStartingRecordingInputFromSaveState() && - !Movie::IsJustStartingPlayingInputFromSaveState()) - Movie::EndPlayInput(false); - } - else - { - Core::DisplayMessage("The savestate could not be loaded", OSD::Duration::NORMAL); - - // since we could be in an inconsistent state now (and might crash or whatever), undo. - if (g_loadDepth < 2) - UndoLoadState(); - } - } - - if (s_on_after_load_callback) - s_on_after_load_callback(); - - g_loadDepth--; - }); + Core::RunOnCPUThread( + [&] { + g_loadDepth++; + + // Save temp buffer for undo load state + if (!Movie::IsJustStartingRecordingInputFromSaveState()) + { + std::lock_guard<std::mutex> lk(g_cs_undo_load_buffer); + SaveToBuffer(g_undo_load_buffer); + if (Movie::IsMovieActive()) + Movie::SaveRecording(File::GetUserPath(D_STATESAVES_IDX) + "undo.dtm"); + else if (File::Exists(File::GetUserPath(D_STATESAVES_IDX) + "undo.dtm")) + File::Delete(File::GetUserPath(D_STATESAVES_IDX) + "undo.dtm"); + } + + bool loaded = false; + bool loadedSuccessfully = false; + + // brackets here are so buffer gets freed ASAP + { + std::vector<u8> buffer; + LoadFileStateData(filename, buffer); + + if (!buffer.empty()) + { + u8* ptr = &buffer[0]; + PointerWrap p(&ptr, PointerWrap::MODE_READ); + DoState(p); + loaded = true; + loadedSuccessfully = (p.GetMode() == PointerWrap::MODE_READ); + } + } + + if (loaded) + { + if (loadedSuccessfully) + { + Core::DisplayMessage(StringFromFormat("Loaded state from %s", filename.c_str()), 2000); + if (File::Exists(filename + ".dtm")) + Movie::LoadInput(filename + ".dtm"); + else if (!Movie::IsJustStartingRecordingInputFromSaveState() && + !Movie::IsJustStartingPlayingInputFromSaveState()) + Movie::EndPlayInput(false); + } + else + { + Core::DisplayMessage("The savestate could not be loaded", OSD::Duration::NORMAL); + + // since we could be in an inconsistent state now (and might crash or whatever), undo. + if (g_loadDepth < 2) + UndoLoadState(); + } + } + + if (s_on_after_load_callback) + s_on_after_load_callback(); + + g_loadDepth--; + }, + true); } void SetOnAfterLoadCallback(AfterLoadCallbackFunc callback) |
