Browse Source

[hle] make ButtonPoller + EventObserver use jthread()

Signed-off-by: lizzie <lizzie@eden-emu.dev>
lizzie/jthread74573785
lizzie 3 weeks ago
parent
commit
6d08cb3c15
  1. 41
      src/core/hle/service/am/button_poller.cpp
  2. 6
      src/core/hle/service/am/button_poller.h
  3. 42
      src/core/hle/service/am/event_observer.cpp
  4. 16
      src/core/hle/service/am/event_observer.h

41
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-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
@ -38,12 +38,11 @@ ButtonPoller::ButtonPoller(Core::System& system, WindowSystem& window_system)
: m_window_system(window_system) { : m_window_system(window_system) {
// TODO: am reads this from the home button state in hid, which is controller-agnostic. // TODO: am reads this from the home button state in hid, which is controller-agnostic.
Core::HID::ControllerUpdateCallback engine_callback{ 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, .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 = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
m_player1_key = m_player1->SetCallback(engine_callback); 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() { ButtonPoller::~ButtonPoller() {
m_handheld->DeleteCallback(m_handheld_key); m_handheld->DeleteCallback(m_handheld_key);
m_player1->DeleteCallback(m_player1_key); m_player1->DeleteCallback(m_player1_key);
m_stop = true;
m_cv.notify_all();
if (m_thread.joinable()) { if (m_thread.joinable()) {
m_thread.request_stop();
m_cv.notify_all();
m_thread.join(); 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 } // namespace Service::AM

6
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-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
@ -33,7 +33,6 @@ public:
private: private:
void OnButtonStateChanged(); void OnButtonStateChanged();
void ThreadLoop();
private: private:
WindowSystem& m_window_system; WindowSystem& m_window_system;
@ -51,8 +50,7 @@ private:
bool m_capture_button_long_sent{}; bool m_capture_button_long_sent{};
bool m_power_button_long_sent{}; bool m_power_button_long_sent{};
std::thread m_thread;
std::atomic<bool> m_stop{false};
std::jthread m_thread;
std::condition_variable m_cv; std::condition_variable m_cv;
std::mutex m_mutex; std::mutex m_mutex;
}; };

42
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-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // 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_window_system.SetEventObserver(this);
m_wakeup_holder.SetUserData(static_cast<uintptr_t>(UserDataTag::WakeupEvent)); m_wakeup_holder.SetUserData(static_cast<uintptr_t>(UserDataTag::WakeupEvent));
m_wakeup_holder.LinkToMultiWait(std::addressof(m_multi_wait)); 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() { 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. // Free remaining owned sessions.
auto it = m_process_holder_list.begin(); auto it = m_process_holder_list.begin();
@ -73,12 +86,12 @@ void EventObserver::LinkDeferred() {
m_multi_wait.MoveAll(std::addressof(m_deferred_wait_list)); m_multi_wait.MoveAll(std::addressof(m_deferred_wait_list));
} }
MultiWaitHolder* EventObserver::WaitSignaled() {
MultiWaitHolder* EventObserver::WaitSignaled(std::stop_token stop_token) {
while (true) { while (true) {
this->LinkDeferred(); this->LinkDeferred();
// If we're done, return before we start waiting. // If we're done, return before we start waiting.
if (m_stop_source.stop_requested()) {
if (stop_token.stop_requested()) {
return nullptr; return nullptr;
} }
@ -116,7 +129,6 @@ void EventObserver::OnProcessEvent(ProcessHolder* holder) {
// Check process state. // Check process state.
auto& applet = holder->GetApplet(); auto& applet = holder->GetApplet();
auto& process = holder->GetProcess(); auto& process = holder->GetProcess();
{ {
std::scoped_lock lk{m_lock, applet.lock}; std::scoped_lock lk{m_lock, applet.lock};
if (process.IsTerminated()) { if (process.IsTerminated()) {
@ -141,22 +153,8 @@ void EventObserver::OnProcessEvent(ProcessHolder* holder) {
void EventObserver::DestroyAppletProcessHolderLocked(ProcessHolder* holder) { void EventObserver::DestroyAppletProcessHolderLocked(ProcessHolder* holder) {
// Remove from owned list. // Remove from owned list.
m_process_holder_list.erase(m_process_holder_list.iterator_to(*holder)); m_process_holder_list.erase(m_process_holder_list.iterator_to(*holder));
// Destroy and free. // Destroy and free.
delete holder; 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 } // namespace Service::AM

16
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-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -29,22 +32,14 @@ public:
private: private:
void LinkDeferred(); void LinkDeferred();
MultiWaitHolder* WaitSignaled();
MultiWaitHolder* WaitSignaled(std::stop_token stop_token);
void Process(MultiWaitHolder* holder); void Process(MultiWaitHolder* holder);
bool WaitAndProcessImpl(); bool WaitAndProcessImpl();
void LoopProcess(); void LoopProcess();
private:
void OnWakeupEvent(MultiWaitHolder* holder); void OnWakeupEvent(MultiWaitHolder* holder);
void OnProcessEvent(ProcessHolder* holder); void OnProcessEvent(ProcessHolder* holder);
private:
void DestroyAppletProcessHolderLocked(ProcessHolder* holder); void DestroyAppletProcessHolderLocked(ProcessHolder* holder);
private:
void ThreadFunc();
private:
// System reference and context. // System reference and context.
Core::System& m_system; Core::System& m_system;
KernelHelpers::ServiceContext m_context; KernelHelpers::ServiceContext m_context;
@ -67,8 +62,7 @@ private:
MultiWait m_deferred_wait_list; MultiWait m_deferred_wait_list;
// Processing thread. // Processing thread.
std::thread m_thread{};
std::stop_source m_stop_source{};
std::jthread m_thread{};
}; };
} // namespace Service::AM } // namespace Service::AM
Loading…
Cancel
Save