hle: kernel: service_thread: Use std::jthread.

- Fixes a potential deadlock on service thread shutdown.
master
bunnei 2021-11-28 13:05:18 +07:00
parent a2384a18fa
commit efb5de1c5f
1 changed files with 19 additions and 18 deletions

@ -25,24 +25,27 @@ public:
void QueueSyncRequest(KSession& session, std::shared_ptr<HLERequestContext>&& context);
private:
std::vector<std::thread> threads;
std::vector<std::jthread> threads;
std::queue<std::function<void()>> requests;
std::mutex queue_mutex;
std::condition_variable condition;
std::condition_variable_any condition;
const std::string service_name;
bool stop{};
};
ServiceThread::Impl::Impl(KernelCore& kernel, std::size_t num_threads, const std::string& name)
: service_name{name} {
for (std::size_t i = 0; i < num_threads; ++i)
threads.emplace_back([this, &kernel] {
for (std::size_t i = 0; i < num_threads; ++i) {
threads.emplace_back([this, &kernel](std::stop_token stop_token) {
Common::SetCurrentThreadName(std::string{"yuzu:HleService:" + service_name}.c_str());
// Wait for first request before trying to acquire a render context
{
std::unique_lock lock{queue_mutex};
condition.wait(lock, [this] { return stop || !requests.empty(); });
condition.wait(lock, stop_token, [this] { return !requests.empty(); });
}
if (stop_token.stop_requested()) {
return;
}
kernel.RegisterHostThread();
@ -52,10 +55,16 @@ ServiceThread::Impl::Impl(KernelCore& kernel, std::size_t num_threads, const std
{
std::unique_lock lock{queue_mutex};
condition.wait(lock, [this] { return stop || !requests.empty(); });
if (stop || requests.empty()) {
condition.wait(lock, stop_token, [this] { return !requests.empty(); });
if (stop_token.stop_requested()) {
return;
}
if (requests.empty()) {
continue;
}
task = std::move(requests.front());
requests.pop();
}
@ -63,6 +72,7 @@ ServiceThread::Impl::Impl(KernelCore& kernel, std::size_t num_threads, const std
task();
}
});
}
}
void ServiceThread::Impl::QueueSyncRequest(KSession& session,
@ -87,16 +97,7 @@ void ServiceThread::Impl::QueueSyncRequest(KSession& session,
condition.notify_one();
}
ServiceThread::Impl::~Impl() {
{
std::unique_lock lock{queue_mutex};
stop = true;
}
condition.notify_all();
for (std::thread& thread : threads) {
thread.join();
}
}
ServiceThread::Impl::~Impl() = default;
ServiceThread::ServiceThread(KernelCore& kernel, std::size_t num_threads, const std::string& name)
: impl{std::make_unique<Impl>(kernel, num_threads, name)} {}