Core/State: Use UniqueBuffer instead of make_unique and std::vector for save state buffers.

This commit is contained in:
Jordan Woyak 2025-04-18 21:30:32 -05:00
parent 88608fd6e1
commit 706f248430
2 changed files with 28 additions and 38 deletions

View file

@ -4,7 +4,6 @@
#include "Core/State.h"
#include <algorithm>
#include <atomic>
#include <condition_variable>
#include <filesystem>
#include <locale>
@ -12,7 +11,6 @@
#include <memory>
#include <mutex>
#include <string>
#include <thread>
#include <utility>
#include <vector>
@ -31,12 +29,10 @@
#include "Common/MsgHandler.h"
#include "Common/Thread.h"
#include "Common/TimeUtil.h"
#include "Common/Timer.h"
#include "Common/Version.h"
#include "Common/WorkQueueThread.h"
#include "Core/AchievementManager.h"
#include "Core/Config/AchievementSettings.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/CoreTiming.h"
@ -46,7 +42,7 @@
#include "Core/HW/Wiimote.h"
#include "Core/Host.h"
#include "Core/Movie.h"
#include "Core/NetPlayClient.h"
#include "Core/NetPlayProto.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
@ -71,14 +67,14 @@ static unsigned char __LZO_MMODEL out[OUT_LEN];
static AfterLoadCallbackFunc s_on_after_load_callback;
// Temporary undo state buffer
static std::vector<u8> s_undo_load_buffer;
static Common::UniqueBuffer<u8> s_undo_load_buffer;
static std::mutex s_undo_load_buffer_mutex;
static std::mutex s_load_or_save_in_progress_mutex;
struct CompressAndDumpState_args
{
std::vector<u8> buffer_vector;
Common::UniqueBuffer<u8> buffer;
std::string filename;
std::shared_ptr<Common::Event> state_write_done_event;
};
@ -205,7 +201,7 @@ static void DoState(Core::System& system, PointerWrap& p)
#endif // USE_RETRO_ACHIEVEMENTS
}
void LoadFromBuffer(Core::System& system, std::vector<u8>& buffer)
void LoadFromBuffer(Core::System& system, Common::UniqueBuffer<u8>& buffer)
{
if (NetPlay::IsNetPlayRunning())
{
@ -229,7 +225,7 @@ void LoadFromBuffer(Core::System& system, std::vector<u8>& buffer)
true);
}
void SaveToBuffer(Core::System& system, std::vector<u8>& buffer)
void SaveToBuffer(Core::System& system, Common::UniqueBuffer<u8>& buffer)
{
Core::RunOnCPUThread(
system,
@ -239,7 +235,7 @@ void SaveToBuffer(Core::System& system, std::vector<u8>& buffer)
DoState(system, p_measure);
const size_t buffer_size = reinterpret_cast<size_t>(ptr);
buffer.resize(buffer_size);
buffer = Common::UniqueBuffer<u8>(buffer_size);
ptr = buffer.data();
PointerWrap p(&ptr, buffer_size, PointerWrap::Mode::Write);
@ -318,15 +314,14 @@ static void CompressBufferToFile(const u8* raw_buffer, u64 size, File::IOFile& f
while (true)
{
u64 bytes_left_to_compress = size - total_bytes_compressed;
const u64 bytes_left_to_compress = size - total_bytes_compressed;
int bytes_to_compress =
const int bytes_to_compress =
static_cast<int>(std::min(static_cast<u64>(LZ4_MAX_INPUT_SIZE), bytes_left_to_compress));
int compressed_buffer_size = LZ4_compressBound(bytes_to_compress);
auto compressed_buffer = std::make_unique<char[]>(compressed_buffer_size);
s32 compressed_len =
LZ4_compress_default(reinterpret_cast<const char*>(raw_buffer) + total_bytes_compressed,
compressed_buffer.get(), bytes_to_compress, compressed_buffer_size);
Common::UniqueBuffer<char> compressed_buffer(LZ4_compressBound(bytes_to_compress));
const int compressed_len = LZ4_compress_default(
reinterpret_cast<const char*>(raw_buffer) + total_bytes_compressed, compressed_buffer.get(),
bytes_to_compress, int(compressed_buffer.size()));
if (compressed_len == 0)
{
@ -380,8 +375,8 @@ static void WriteHeadersToFile(size_t uncompressed_size, File::IOFile& f)
static void CompressAndDumpState(Core::System& system, CompressAndDumpState_args& save_args)
{
const u8* const buffer_data = save_args.buffer_vector.data();
const size_t buffer_size = save_args.buffer_vector.size();
const u8* const buffer_data = save_args.buffer.data();
const size_t buffer_size = save_args.buffer.size();
const std::string& filename = save_args.filename;
// Find free temporary filename.
@ -485,8 +480,7 @@ void SaveAs(Core::System& system, const std::string& filename, bool wait)
const size_t buffer_size = reinterpret_cast<size_t>(ptr);
// Then actually do the write.
std::vector<u8> current_buffer;
current_buffer.resize(buffer_size);
Common::UniqueBuffer<u8> current_buffer(buffer_size);
ptr = current_buffer.data();
PointerWrap p(&ptr, buffer_size, PointerWrap::Mode::Write);
DoState(system, p);
@ -498,7 +492,7 @@ void SaveAs(Core::System& system, const std::string& filename, bool wait)
std::shared_ptr<Common::Event> sync_event;
CompressAndDumpState_args save_args;
save_args.buffer_vector = std::move(current_buffer);
save_args.buffer = std::move(current_buffer);
save_args.filename = filename;
if (wait)
{
@ -531,8 +525,7 @@ static bool GetVersionFromLZO(StateHeader& header, File::IOFile& f)
// Just read the first block, since it will contain the full revision string
lzo_uint32 cur_len = 0; // size of compressed bytes
lzo_uint new_len = 0; // size of uncompressed bytes
std::vector<u8> buffer;
buffer.resize(header.legacy_header.lzo_size);
Common::UniqueBuffer<u8> buffer(header.legacy_header.lzo_size);
if (!f.ReadArray(&cur_len, 1) || !f.ReadBytes(out, cur_len))
return false;
@ -563,11 +556,9 @@ static bool GetVersionFromLZO(StateHeader& header, File::IOFile& f)
// Read in the string
if (buffer.size() >= sizeof(StateHeaderVersion) + header.version_header.version_string_length)
{
auto version_buffer = std::make_unique<char[]>(header.version_header.version_string_length);
memcpy(version_buffer.get(), buffer.data() + sizeof(StateHeaderVersion),
header.version_header.version_string_length);
header.version_string =
std::string(version_buffer.get(), header.version_header.version_string_length);
header.version_string.assign(
reinterpret_cast<char*>(buffer.data() + sizeof(StateHeaderVersion)),
header.version_header.version_string_length);
}
else
{
@ -613,15 +604,14 @@ static bool ReadStateHeaderFromFile(StateHeader& header, File::IOFile& f,
return false;
}
auto version_buffer = std::make_unique<char[]>(header.version_header.version_string_length);
if (!f.ReadBytes(version_buffer.get(), header.version_header.version_string_length))
std::string version_buffer(header.version_header.version_string_length, '\0');
if (!f.ReadBytes(version_buffer.data(), version_buffer.size()))
{
Core::DisplayMessage("Failed to read state version string", 2000);
return false;
}
header.version_string =
std::string(version_buffer.get(), header.version_header.version_string_length);
header.version_string = std::move(version_buffer);
}
return true;
@ -681,7 +671,7 @@ static bool DecompressLZ4(std::vector<u8>& raw_buffer, u64 size, File::IOFile& f
return false;
}
auto compressed_data = std::make_unique<char[]>(compressed_data_len);
Common::UniqueBuffer<char> compressed_data(compressed_data_len);
if (!f.ReadBytes(compressed_data.get(), compressed_data_len))
{
PanicAlertFmt("Could not read state data");
@ -959,7 +949,7 @@ void Shutdown()
// never)
{
std::lock_guard lk(s_undo_load_buffer_mutex);
std::vector<u8>().swap(s_undo_load_buffer);
decltype(s_undo_load_buffer)().swap(s_undo_load_buffer);
}
}

View file

@ -9,8 +9,8 @@
#include <functional>
#include <string>
#include <type_traits>
#include <vector>
#include "Common/Buffer.h"
#include "Common/CommonTypes.h"
namespace Core
@ -106,8 +106,8 @@ void Load(Core::System& system, int slot);
void SaveAs(Core::System& system, const std::string& filename, bool wait = false);
void LoadAs(Core::System& system, const std::string& filename);
void SaveToBuffer(Core::System& system, std::vector<u8>& buffer);
void LoadFromBuffer(Core::System& system, std::vector<u8>& buffer);
void SaveToBuffer(Core::System& system, Common::UniqueBuffer<u8>& buffer);
void LoadFromBuffer(Core::System& system, const Common::UniqueBuffer<u8>& buffer);
void LoadLastSaved(Core::System& system, int i = 1);
void SaveFirstSaved(Core::System& system);