From 96be40bf30e6938fefe21a026a97130d5009cc04 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 22 Feb 2020 14:46:49 +0300 Subject: [PATCH] Implement cellMsgDialog closing thread Fixing deprecation warning. --- rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp | 95 ++++++++++++++++-------- 1 file changed, 66 insertions(+), 29 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp b/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp index 73b6df498f..5e10191add 100644 --- a/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp +++ b/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp @@ -13,6 +13,8 @@ LOG_CHANNEL(cellSysutil); +extern u64 get_guest_system_time(); + template<> void fmt_class_string::format(std::string& out, u64 arg) { @@ -79,6 +81,59 @@ struct msg_info } }; +struct msg_dlg_thread_info +{ + atomic_t wait_until = 0; + + void operator()() + { + while (thread_ctrl::state() != thread_state::aborting) + { + const u64 new_value = wait_until.load(); + + if (new_value == 0) + { + wait_until.wait(0); + continue; + } + + while (get_guest_system_time() < new_value) + { + if (wait_until.load() != new_value) + break; + + std::this_thread::sleep_for(10ms); + } + + if (auto manager = g_fxo->get()) + { + if (auto dlg = manager->get()) + { + if (!wait_until.compare_and_swap_test(new_value, 0)) + { + continue; + } + + dlg->close(); + } + } + else if (const auto dlg = g_fxo->get()->get()) + { + if (!wait_until.compare_and_swap_test(new_value, 0)) + { + continue; + } + + dlg->on_close(CELL_MSGDIALOG_BUTTON_NONE); + } + } + } + + static constexpr auto thread_name = "MsgDialog Close Thread"sv; +}; + +using msg_dlg_thread = named_thread; + // variable used to immediately get the response from auxiliary message dialogs (callbacks would be async) atomic_t g_last_user_response = CELL_MSGDIALOG_BUTTON_NONE; @@ -140,6 +195,7 @@ error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr msgString, }); } + g_fxo->get()->wait_until = 0; g_fxo->get()->remove(); } @@ -368,31 +424,19 @@ error_code cellMsgDialogClose(f32 delay) { cellSysutil.warning("cellMsgDialogClose(delay=%f)", delay); - extern u64 get_guest_system_time(); const u64 wait_until = get_guest_system_time() + static_cast(std::max(delay, 0.0f) * 1000); if (auto manager = g_fxo->get()) { if (auto dlg = manager->get()) { - thread_ctrl::spawn("cellMsgDialogClose() Thread", [=] - { - while (get_guest_system_time() < wait_until) - { - if (Emu.IsStopped()) - return; - - if (manager->get() != dlg) - return; - - std::this_thread::sleep_for(1ms); - } - - dlg->close(); - }); - + const auto thr = g_fxo->get(); + thr->wait_until = wait_until; + thr->wait_until.notify_one(); return CELL_OK; } + + return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED; } const auto dlg = g_fxo->get()->get(); @@ -402,18 +446,9 @@ error_code cellMsgDialogClose(f32 delay) return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED; } - thread_ctrl::spawn("cellMsgDialogClose() Thread", [=]() - { - while (dlg->state == MsgDialogState::Open && get_guest_system_time() < wait_until) - { - if (Emu.IsStopped()) return; - - std::this_thread::sleep_for(1ms); - } - - dlg->on_close(CELL_MSGDIALOG_BUTTON_NONE); - }); - + const auto thr = g_fxo->get(); + thr->wait_until = wait_until; + thr->wait_until.notify_one(); return CELL_OK; } @@ -425,6 +460,7 @@ error_code cellMsgDialogAbort() { if (auto dlg = manager->get()) { + g_fxo->get()->wait_until = 0; dlg->close(false); return CELL_OK; } @@ -442,6 +478,7 @@ error_code cellMsgDialogAbort() return CELL_SYSUTIL_ERROR_BUSY; } + g_fxo->get()->wait_until = 0; g_fxo->get()->remove(); // this shouldn't call on_close pad::SetIntercepted(false); // so we need to reenable the pads here