From 6d08cb3c15d38cb73d321e223dbaff6d759884fb Mon Sep 17 00:00:00 2001 From: lizzie Date: Sun, 17 May 2026 23:41:37 +0000 Subject: [PATCH] [hle] make ButtonPoller + EventObserver use jthread() Signed-off-by: lizzie --- src/core/hle/service/am/button_poller.cpp | 41 ++++++++++----------- src/core/hle/service/am/button_poller.h | 6 ++-- src/core/hle/service/am/event_observer.cpp | 42 +++++++++++----------- src/core/hle/service/am/event_observer.h | 16 +++------ 4 files changed, 46 insertions(+), 59 deletions(-) diff --git a/src/core/hle/service/am/button_poller.cpp b/src/core/hle/service/am/button_poller.cpp index 069a1934d4..a881e8af26 100644 --- a/src/core/hle/service/am/button_poller.cpp +++ b/src/core/hle/service/am/button_poller.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -38,12 +38,11 @@ ButtonPoller::ButtonPoller(Core::System& system, WindowSystem& window_system) : m_window_system(window_system) { // TODO: am reads this from the home button state in hid, which is controller-agnostic. Core::HID::ControllerUpdateCallback engine_callback{ - .on_change = - [this](Core::HID::ControllerTriggerType type) { - if (type == Core::HID::ControllerTriggerType::Button) { - this->OnButtonStateChanged(); - } - }, + .on_change = [this](Core::HID::ControllerTriggerType type) { + if (type == Core::HID::ControllerTriggerType::Button) { + this->OnButtonStateChanged(); + } + }, .is_npad_service = true, }; @@ -52,15 +51,25 @@ ButtonPoller::ButtonPoller(Core::System& system, WindowSystem& window_system) m_player1 = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); m_player1_key = m_player1->SetCallback(engine_callback); - m_thread = std::thread([this] { this->ThreadLoop(); }); + m_thread = std::jthread([this](std::stop_token stop_token) { + using namespace std::chrono_literals; + std::unique_lock lk{m_mutex}; + while (!stop_token.stop_requested()) { + m_cv.wait_for(lk, 50ms); + if (stop_token.stop_requested()) break; + lk.unlock(); + OnButtonStateChanged(); + lk.lock(); + } + }); } ButtonPoller::~ButtonPoller() { m_handheld->DeleteCallback(m_handheld_key); m_player1->DeleteCallback(m_player1_key); - m_stop = true; - m_cv.notify_all(); if (m_thread.joinable()) { + m_thread.request_stop(); + m_cv.notify_all(); m_thread.join(); } } @@ -130,16 +139,4 @@ void ButtonPoller::OnButtonStateChanged() { // } } -void ButtonPoller::ThreadLoop() { - using namespace std::chrono_literals; - std::unique_lock lk{m_mutex}; - while (!m_stop) { - m_cv.wait_for(lk, 50ms); - if (m_stop) break; - lk.unlock(); - OnButtonStateChanged(); - lk.lock(); - } -} - } // namespace Service::AM diff --git a/src/core/hle/service/am/button_poller.h b/src/core/hle/service/am/button_poller.h index 12e7035aa1..8089b3c284 100644 --- a/src/core/hle/service/am/button_poller.h +++ b/src/core/hle/service/am/button_poller.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -33,7 +33,6 @@ public: private: void OnButtonStateChanged(); - void ThreadLoop(); private: WindowSystem& m_window_system; @@ -51,8 +50,7 @@ private: bool m_capture_button_long_sent{}; bool m_power_button_long_sent{}; - std::thread m_thread; - std::atomic m_stop{false}; + std::jthread m_thread; std::condition_variable m_cv; std::mutex m_mutex; }; diff --git a/src/core/hle/service/am/event_observer.cpp b/src/core/hle/service/am/event_observer.cpp index 5d1d303ed3..431c8a3009 100644 --- a/src/core/hle/service/am/event_observer.cpp +++ b/src/core/hle/service/am/event_observer.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -20,14 +23,24 @@ EventObserver::EventObserver(Core::System& system, WindowSystem& window_system) m_window_system.SetEventObserver(this); m_wakeup_holder.SetUserData(static_cast(UserDataTag::WakeupEvent)); m_wakeup_holder.LinkToMultiWait(std::addressof(m_multi_wait)); - m_thread = std::thread([&] { this->ThreadFunc(); }); + m_thread = std::jthread([&](std::stop_token stop_token) { + Common::SetCurrentThreadName("am:EventObserver"); + while (!stop_token.stop_requested()) { + auto* signaled_holder = this->WaitSignaled(stop_token); + if (!signaled_holder) + break; + this->Process(signaled_holder); + } + }); } EventObserver::~EventObserver() { - // Signal thread and wait for processing to finish. - m_stop_source.request_stop(); - m_wakeup_event.Signal(); - m_thread.join(); + if (m_thread.joinable()) { + // Signal thread and wait for processing to finish. + m_thread.request_stop(); + m_wakeup_event.Signal(); + m_thread.join(); + } // Free remaining owned sessions. auto it = m_process_holder_list.begin(); @@ -73,12 +86,12 @@ void EventObserver::LinkDeferred() { m_multi_wait.MoveAll(std::addressof(m_deferred_wait_list)); } -MultiWaitHolder* EventObserver::WaitSignaled() { +MultiWaitHolder* EventObserver::WaitSignaled(std::stop_token stop_token) { while (true) { this->LinkDeferred(); // If we're done, return before we start waiting. - if (m_stop_source.stop_requested()) { + if (stop_token.stop_requested()) { return nullptr; } @@ -116,7 +129,6 @@ void EventObserver::OnProcessEvent(ProcessHolder* holder) { // Check process state. auto& applet = holder->GetApplet(); auto& process = holder->GetProcess(); - { std::scoped_lock lk{m_lock, applet.lock}; if (process.IsTerminated()) { @@ -141,22 +153,8 @@ void EventObserver::OnProcessEvent(ProcessHolder* holder) { void EventObserver::DestroyAppletProcessHolderLocked(ProcessHolder* holder) { // Remove from owned list. m_process_holder_list.erase(m_process_holder_list.iterator_to(*holder)); - // Destroy and free. delete holder; } -void EventObserver::ThreadFunc() { - Common::SetCurrentThreadName("am:EventObserver"); - - while (true) { - auto* signaled_holder = this->WaitSignaled(); - if (!signaled_holder) { - break; - } - - this->Process(signaled_holder); - } -} - } // namespace Service::AM diff --git a/src/core/hle/service/am/event_observer.h b/src/core/hle/service/am/event_observer.h index 3e52e8494d..c66eb711c8 100644 --- a/src/core/hle/service/am/event_observer.h +++ b/src/core/hle/service/am/event_observer.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -29,22 +32,14 @@ public: private: void LinkDeferred(); - MultiWaitHolder* WaitSignaled(); + MultiWaitHolder* WaitSignaled(std::stop_token stop_token); void Process(MultiWaitHolder* holder); bool WaitAndProcessImpl(); void LoopProcess(); - -private: void OnWakeupEvent(MultiWaitHolder* holder); void OnProcessEvent(ProcessHolder* holder); - -private: void DestroyAppletProcessHolderLocked(ProcessHolder* holder); -private: - void ThreadFunc(); - -private: // System reference and context. Core::System& m_system; KernelHelpers::ServiceContext m_context; @@ -67,8 +62,7 @@ private: MultiWait m_deferred_wait_list; // Processing thread. - std::thread m_thread{}; - std::stop_source m_stop_source{}; + std::jthread m_thread{}; }; } // namespace Service::AM