// Copyright 2023 Dolphin Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include #include "Common/CommonTypes.h" class TASControlState { public: // Call this from the CPU thread to get the current value. (This function can also safely be // called from the UI thread, but you're effectively just getting the value the UI control has.) u16 GetValue() const; // Call this from the CPU thread when the controller state changes. // If the return value is true, queue up a call to ApplyControllerChangeValue on the UI thread. bool OnControllerValueChanged(u16 new_value); // Call this from the UI thread when the user changes the value using the UI. void OnUIValueChanged(u16 new_value); // Call this from the UI thread after OnControllerValueChanged returns true, // and set the state of the UI control to the return value. u16 ApplyControllerValueChange(); private: // A description of how threading is handled: The UI thread can update its copy of the state // whenever it wants to, and must *not* increment the version when doing so. The CPU thread can // update its copy of the state whenever it wants to, and *must* increment the version when doing // so. When the CPU thread updates its copy of the state, the UI thread should then (possibly // after a delay) mirror the change by copying the CPU thread's state to the UI thread's state. // This mirroring is the only way for the version number stored in the UI thread's state to // change. The version numbers of the two copies can be compared to check if the UI thread's view // of what has happened on the CPU thread is up to date. struct State { u16 version = 0; u16 value = 0; }; std::atomic m_ui_thread_state; std::atomic m_cpu_thread_state; };