mirror of
https://github.com/Retropex/dolphin.git
synced 2025-05-22 18:12:34 +02:00

Turns out that we have two subsystems that want to register CPU thread callbacks from a different thread than the CPU thread: FreeLookConfig and VideoConfig. Both seem to happen from the host thread before the CPU thread starts, so there's no thread safety issue. But ideally, if we want to allow registering callbacks from threads other than the CPU thread, we should make registering callbacks actually thread-safe. This is an unsolved problem for the regular Config system, so I would like to leave it outside the scope of this PR.
76 lines
1.6 KiB
C++
76 lines
1.6 KiB
C++
// Copyright 2023 Dolphin Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include "Core/CPUThreadConfigCallback.h"
|
|
|
|
#include <atomic>
|
|
|
|
#include "Common/Assert.h"
|
|
#include "Common/Config/Config.h"
|
|
#include "Core/Core.h"
|
|
|
|
namespace
|
|
{
|
|
std::atomic<bool> s_should_run_callbacks = false;
|
|
|
|
static std::vector<
|
|
std::pair<CPUThreadConfigCallback::ConfigChangedCallbackID, Config::ConfigChangedCallback>>
|
|
s_callbacks;
|
|
|
|
static size_t s_next_callback_id = 0;
|
|
|
|
void RunCallbacks()
|
|
{
|
|
for (const auto& callback : s_callbacks)
|
|
callback.second();
|
|
}
|
|
|
|
void OnConfigChanged()
|
|
{
|
|
if (Core::IsCPUThread())
|
|
{
|
|
s_should_run_callbacks.store(false, std::memory_order_relaxed);
|
|
RunCallbacks();
|
|
}
|
|
else
|
|
{
|
|
s_should_run_callbacks.store(true, std::memory_order_relaxed);
|
|
}
|
|
}
|
|
|
|
}; // namespace
|
|
|
|
namespace CPUThreadConfigCallback
|
|
{
|
|
ConfigChangedCallbackID AddConfigChangedCallback(Config::ConfigChangedCallback func)
|
|
{
|
|
static auto s_config_changed_callback_id = Config::AddConfigChangedCallback(&OnConfigChanged);
|
|
|
|
const ConfigChangedCallbackID callback_id{s_next_callback_id};
|
|
++s_next_callback_id;
|
|
s_callbacks.emplace_back(std::make_pair(callback_id, std::move(func)));
|
|
return callback_id;
|
|
}
|
|
|
|
void RemoveConfigChangedCallback(ConfigChangedCallbackID callback_id)
|
|
{
|
|
for (auto it = s_callbacks.begin(); it != s_callbacks.end(); ++it)
|
|
{
|
|
if (it->first == callback_id)
|
|
{
|
|
s_callbacks.erase(it);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CheckForConfigChanges()
|
|
{
|
|
DEBUG_ASSERT(Core::IsCPUThread());
|
|
|
|
if (s_should_run_callbacks.exchange(false, std::memory_order_relaxed))
|
|
RunCallbacks();
|
|
}
|
|
|
|
}; // namespace CPUThreadConfigCallback
|