mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-06-28 09:45:45 +02:00
[hle] make ButtonPoller + EventObserver use jthread()
Signed-off-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
parent
ca6bb3ae1d
commit
6d08cb3c15
4 changed files with 46 additions and 59 deletions
|
|
@ -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 =
|
.on_change = [this](Core::HID::ControllerTriggerType type) {
|
||||||
[this](Core::HID::ControllerTriggerType type) {
|
if (type == Core::HID::ControllerTriggerType::Button) {
|
||||||
if (type == Core::HID::ControllerTriggerType::Button) {
|
this->OnButtonStateChanged();
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -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::jthread m_thread;
|
||||||
std::atomic<bool> m_stop{false};
|
|
||||||
std::condition_variable m_cv;
|
std::condition_variable m_cv;
|
||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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.
|
if (m_thread.joinable()) {
|
||||||
m_stop_source.request_stop();
|
// Signal thread and wait for processing to finish.
|
||||||
m_wakeup_event.Signal();
|
m_thread.request_stop();
|
||||||
m_thread.join();
|
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
|
||||||
|
|
|
||||||
|
|
@ -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::jthread m_thread{};
|
||||||
std::stop_source m_stop_source{};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue