From 16a31c255404eb7d1ed986a55e8946fb4da12b79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 21 Dec 2023 11:49:25 +0100 Subject: [PATCH] Avoid spamming the keymap lock during input processing --- Core/ControlMapper.cpp | 31 ++++++++++++++++++++++--------- Core/KeyMap.cpp | 17 +++++++++++++++-- Core/KeyMap.h | 5 +++++ 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/Core/ControlMapper.cpp b/Core/ControlMapper.cpp index 06722dde09..da84837aae 100644 --- a/Core/ControlMapper.cpp +++ b/Core/ControlMapper.cpp @@ -154,8 +154,11 @@ void ControlMapper::UpdateAnalogOutput(int stick) { } void ControlMapper::ForceReleaseVKey(int vkey) { + // Note: This one is called from an onVKey_ handler, which already holds mutex_. + + KeyMap::LockMappings(); std::vector multiMappings; - if (KeyMap::InputMappingsFromPspButton(vkey, &multiMappings, true)) { + if (KeyMap::InputMappingsFromPspButtonNoLock(vkey, &multiMappings, true)) { double now = time_now_d(); for (const auto &entry : multiMappings) { for (const auto &mapping : entry.mappings) { @@ -165,6 +168,7 @@ void ControlMapper::ForceReleaseVKey(int vkey) { } } } + KeyMap::UnlockMappings(); } static int RotatePSPKeyCode(int x) { @@ -251,7 +255,7 @@ void ControlMapper::SwapMappingIfEnabled(uint32_t *vkey) { } // Can only be called from Key or Axis. -// mutex_ should be locked. +// mutex_ should be locked, and also KeyMap::LockMappings(). // TODO: We should probably make a batched version of this. bool ControlMapper::UpdatePSPState(const InputMapping &changedMapping, double now) { // Instead of taking an input key and finding what it outputs, we loop through the OUTPUTS and @@ -282,7 +286,7 @@ bool ControlMapper::UpdatePSPState(const InputMapping &changedMapping, double no } SwapMappingIfEnabled(&mappingBit); - if (!KeyMap::InputMappingsFromPspButton(mappingBit, &inputMappings, false)) + if (!KeyMap::InputMappingsFromPspButtonNoLock(mappingBit, &inputMappings, false)) continue; // If a mapping could consist of a combo, we could trivially check it here. @@ -319,7 +323,7 @@ bool ControlMapper::UpdatePSPState(const InputMapping &changedMapping, double no uint32_t idForMapping = vkId; SwapMappingIfEnabled(&idForMapping); - if (!KeyMap::InputMappingsFromPspButton(idForMapping, &inputMappings, false)) + if (!KeyMap::InputMappingsFromPspButtonNoLock(idForMapping, &inputMappings, false)) continue; // If a mapping could consist of a combo, we could trivially check it here. @@ -421,15 +425,16 @@ bool ControlMapper::Key(const KeyInput &key, bool *pauseTrigger) { // Claim that we handled this. Prevents volume key repeats from popping up the volume control on Android. return true; } - double now = time_now_d(); - if (key.deviceId < DEVICE_ID_COUNT) { - deviceTimestamps_[(int)key.deviceId] = now; - } + double now = time_now_d(); InputMapping mapping(key.deviceId, key.keyCode); std::lock_guard guard(mutex_); + if (key.deviceId < DEVICE_ID_COUNT) { + deviceTimestamps_[(int)key.deviceId] = now; + } + if (key.flags & KEY_DOWN) { curInput_[mapping] = { 1.0f, now }; } else if (key.flags & KEY_UP) { @@ -446,10 +451,15 @@ bool ControlMapper::Key(const KeyInput &key, bool *pauseTrigger) { } } - return UpdatePSPState(mapping, now); + KeyMap::LockMappings(); + bool retval = UpdatePSPState(mapping, now); + KeyMap::UnlockMappings(); + return retval; } void ControlMapper::ToggleSwapAxes() { + std::lock_guard guard(mutex_); + swapAxes_ = !swapAxes_; updatePSPButtons_(0, CTRL_LEFT | CTRL_RIGHT | CTRL_UP | CTRL_DOWN); @@ -478,6 +488,8 @@ void ControlMapper::Axis(const AxisInput *axes, size_t count) { double now = time_now_d(); std::lock_guard guard(mutex_); + + KeyMap::LockMappings(); for (size_t i = 0; i < count; i++) { const AxisInput &axis = axes[i]; size_t deviceIndex = (size_t)axis.deviceId; // this wraps -1 up high, so will get rejected on the next line. @@ -500,6 +512,7 @@ void ControlMapper::Axis(const AxisInput *axes, size_t count) { UpdatePSPState(opposite, now); } } + KeyMap::UnlockMappings(); } void ControlMapper::Update(double now) { diff --git a/Core/KeyMap.cpp b/Core/KeyMap.cpp index 46a3ecda92..34a92313f4 100644 --- a/Core/KeyMap.cpp +++ b/Core/KeyMap.cpp @@ -524,8 +524,8 @@ bool InputMappingToPspButton(const InputMapping &mapping, std::vector *pspB return found; } -bool InputMappingsFromPspButton(int btn, std::vector *mappings, bool ignoreMouse) { - std::lock_guard guard(g_controllerMapLock); +// This is the main workhorse of the ControlMapper. +bool InputMappingsFromPspButtonNoLock(int btn, std::vector *mappings, bool ignoreMouse) { auto iter = g_controllerMap.find(btn); if (iter == g_controllerMap.end()) { return false; @@ -542,6 +542,19 @@ bool InputMappingsFromPspButton(int btn, std::vector *mapping return mapped; } +bool InputMappingsFromPspButton(int btn, std::vector *mappings, bool ignoreMouse) { + std::lock_guard guard(g_controllerMapLock); + return InputMappingsFromPspButtonNoLock(btn, mappings, ignoreMouse); +} + +void LockMappings() { + g_controllerMapLock.lock(); +} + +void UnlockMappings() { + g_controllerMapLock.unlock(); +} + bool PspButtonHasMappings(int btn) { std::lock_guard guard(g_controllerMapLock); auto iter = g_controllerMap.find(btn); diff --git a/Core/KeyMap.h b/Core/KeyMap.h index 2524610333..00a75befd5 100644 --- a/Core/KeyMap.h +++ b/Core/KeyMap.h @@ -181,6 +181,11 @@ namespace KeyMap { bool InputMappingToPspButton(const InputMapping &mapping, std::vector *pspButtons); bool InputMappingsFromPspButton(int btn, std::vector *keys, bool ignoreMouse); + // Careful with these. + bool InputMappingsFromPspButtonNoLock(int btn, std::vector *keys, bool ignoreMouse); + void LockMappings(); + void UnlockMappings(); + // Simplified check. bool PspButtonHasMappings(int btn);