summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorStenzek <stenzek@gmail.com>2019-06-29 18:25:04 +1000
committerStenzek <stenzek@gmail.com>2019-07-24 04:08:25 +1000
commita25a4e07083d4e20b5be6192892c346c4549ed73 (patch)
tree2228eaeba0ab44e4e798fe422aa094961fd23167 /Source/Core
parentdf45e714a3e7a112e53a79e4b7362c4f8aed84d5 (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.cpp230
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)