Don't use atomics in libretro builds without multithreading support

This commit is contained in:
刘皓 2025-04-26 18:00:06 -04:00
parent 8056cb3774
commit 0d035702a1
No known key found for this signature in database
GPG key ID: 7901753DB465B711

View file

@ -68,8 +68,60 @@ struct lock_guard {
} }
}; };
template <typename T> struct atomic {
#ifdef MKXPZ_HAVE_THREADED_AUDIO
std::atomic<T> atom;
#else
T atom;
#endif // MKXPZ_HAVE_THREADED_AUDIO
atomic() {}
atomic(T value) : atom(value) {}
atomic(const struct atomic &guard) = delete;
atomic(struct atomic &&guard) noexcept = delete;
struct atomic &operator=(const struct atomic &guard) = delete;
struct atomic &operator=(struct atomic &&guard) noexcept = delete;
T load_relaxed() const noexcept {
#ifdef MKXPZ_HAVE_THREADED_AUDIO
return atom.load(std::memory_order_relaxed);
#else
return atom;
#endif // MKXPZ_HAVE_THREADED_AUDIO
}
operator T() const noexcept {
#ifdef MKXPZ_HAVE_THREADED_AUDIO
return atom.load(std::memory_order_seq_cst);
#else
return atom;
#endif // MKXPZ_HAVE_THREADED_AUDIO
}
void operator=(T value) noexcept {
#ifdef MKXPZ_HAVE_THREADED_AUDIO
atom.store(value, std::memory_order_seq_cst);
#else
atom = value;
#endif // MKXPZ_HAVE_THREADED_AUDIO
}
void operator+=(T value) noexcept {
#ifdef MKXPZ_HAVE_THREADED_AUDIO
atom.fetch_add(value, std::memory_order_seq_cst);
#else
atom += value;
#endif // MKXPZ_HAVE_THREADED_AUDIO
}
};
static uint64_t frame_count; static uint64_t frame_count;
static std::atomic<uint64_t> frame_time; static struct atomic<uint64_t> frame_time;
static uint64_t frame_time_remainder; static uint64_t frame_time_remainder;
static uint64_t retro_run_count; static uint64_t retro_run_count;
@ -89,14 +141,14 @@ static retro_system_av_info av_info;
static struct retro_audio_callback audio_callback; static struct retro_audio_callback audio_callback;
static struct retro_frame_time_callback frame_time_callback = { static struct retro_frame_time_callback frame_time_callback = {
.callback = [](retro_usec_t delta) { .callback = [](retro_usec_t delta) {
frame_time.fetch_add(delta, std::memory_order_seq_cst); frame_time += delta;
frame_time_remainder += delta; frame_time_remainder += delta;
}, },
}; };
static std::mutex threaded_audio_mutex; static std::mutex threaded_audio_mutex;
static bool threaded_audio_enabled = false; static bool threaded_audio_enabled = false;
static bool frame_time_callback_enabled = false; static bool frame_time_callback_enabled = false;
static std::atomic<bool> shared_state_initialized(false); static struct atomic<bool> shared_state_initialized(false);
namespace mkxp_retro { namespace mkxp_retro {
retro_log_printf_t log_printf; retro_log_printf_t log_printf;
@ -110,7 +162,7 @@ namespace mkxp_retro {
bool input_polled; bool input_polled;
uint64_t get_ticks() noexcept { uint64_t get_ticks() noexcept {
return frame_time.load(std::memory_order_seq_cst) / 1000; return frame_time / 1000;
} }
double get_refresh_rate() noexcept { double get_refresh_rate() noexcept {
@ -204,7 +256,7 @@ SANDBOX_COROUTINE(main,
) )
static void deinit_sandbox() { static void deinit_sandbox() {
shared_state_initialized.store(false, std::memory_order_seq_cst); shared_state_initialized = false;
struct lock_guard guard(threaded_audio_mutex); struct lock_guard guard(threaded_audio_mutex);
if (sound_buf != NULL) { if (sound_buf != NULL) {
@ -348,7 +400,7 @@ static bool init_sandbox() {
} }
frame_count = 0; frame_count = 0;
frame_time.store(0, std::memory_order_seq_cst); frame_time = 0;
frame_time_remainder = 0; frame_time_remainder = 0;
retro_run_count = 0; retro_run_count = 0;
@ -448,16 +500,16 @@ extern "C" RETRO_API void retro_run() {
if (!frame_time_callback_enabled) { if (!frame_time_callback_enabled) {
uint64_t reference = 1000000 / av_info.timing.fps; uint64_t reference = 1000000 / av_info.timing.fps;
frame_time.fetch_add(reference, std::memory_order_seq_cst); frame_time += reference;
frame_time_remainder += reference; frame_time_remainder += reference;
} }
input_polled = false; input_polled = false;
// We deferred initializing the shared state since the OpenGL symbols aren't available until the first call to `retro_run()` // We deferred initializing the shared state since the OpenGL symbols aren't available until the first call to `retro_run()`
if (!shared_state_initialized.load(std::memory_order_relaxed)) { if (!shared_state_initialized.load_relaxed()) {
SharedState::initInstance(&thread_data.get()); SharedState::initInstance(&thread_data.get());
shared_state_initialized.store(true, std::memory_order_seq_cst); shared_state_initialized = true;
} else if (hw_render.context_type != RETRO_HW_CONTEXT_NONE && (should_render || (!dupe_supported && mkxp_retro::sandbox.has_value()))) { } else if (hw_render.context_type != RETRO_HW_CONTEXT_NONE && (should_render || (!dupe_supported && mkxp_retro::sandbox.has_value()))) {
glState.reset(); glState.reset();
} }
@ -602,13 +654,13 @@ extern "C" RETRO_API bool retro_load_game(const struct retro_game_info *info) {
#ifdef MKXPZ_HAVE_THREADED_AUDIO #ifdef MKXPZ_HAVE_THREADED_AUDIO
audio_callback.callback = []() { audio_callback.callback = []() {
if (!shared_state_initialized.load(std::memory_order_seq_cst)) { if (!shared_state_initialized) {
return; return;
} }
struct lock_guard guard(threaded_audio_mutex); struct lock_guard guard(threaded_audio_mutex);
if (!shared_state_initialized.load(std::memory_order_seq_cst)) { if (!shared_state_initialized) {
return; return;
} }