Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions rpcs3/Emu/System.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3895,6 +3895,31 @@ bool Emulator::Quit(bool force_quit)

void Emulator::CleanUp()
{
// Join threads
qt_events_aware_op(50, [&]()
{
if (!g_fxo->is_init())
{
return true;
}

bool has_running = false;

for (const auto& [type, data] : *g_fxo)
{
if (type.thread_op)
{
if (type.thread_op(data, thread_state::aborting) != thread_state::finished)
{
has_running = true;
break;
}
}
}

return has_running == false;
});

// Deinitialize object manager to prevent any hanging objects at program exit
g_fxo->clear();
}
Expand Down
24 changes: 23 additions & 1 deletion rpcs3/Input/gui_pad_thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,18 @@ gui_pad_thread::gui_pad_thread()
m_thread = std::make_unique<named_thread<std::function<void()>>>("Gui Pad Thread", [this](){ run(); });
}

gui_pad_thread::~gui_pad_thread()
gui_pad_thread& gui_pad_thread::operator=(thread_state state) noexcept
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't remember this being an fxo.
Why is any of this necessary?

{
if (state == thread_state::aborting)
{
if (m_thread)
{
*m_thread = state;
}

return *this;
}

// Join thread
m_thread.reset();

Expand All @@ -63,6 +73,18 @@ gui_pad_thread::~gui_pad_thread()
m_uinput_fd = -1;
}
#endif

return *this;
}

gui_pad_thread::operator thread_state() const noexcept
{
return m_thread && *m_thread != thread_state::finished ? m_thread->operator thread_state() : thread_state::finished;
}

gui_pad_thread::~gui_pad_thread()
{
*this = thread_state::finished;
}

void gui_pad_thread::update_settings(const std::shared_ptr<gui_settings>& settings)
Expand Down
2 changes: 2 additions & 0 deletions rpcs3/Input/gui_pad_thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class gui_pad_thread
{
public:
gui_pad_thread();
gui_pad_thread& operator=(thread_state state) noexcept;
operator thread_state() const noexcept;
virtual ~gui_pad_thread();

void update_settings(const std::shared_ptr<gui_settings>& settings);
Expand Down
14 changes: 12 additions & 2 deletions rpcs3/util/fixed_typemap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ namespace stx
struct typeinfo
{
bool(*create)(uchar* ptr, manual_typemap&, utils::serial*, std::string_view) noexcept = nullptr;
void(*thread_op)(void* ptr, thread_state) noexcept = nullptr;
thread_state(*thread_op)(void* ptr, thread_state) noexcept = nullptr;
void(*save)(void* ptr, utils::serial&) noexcept = nullptr;
bool(*saveable)(bool) noexcept = nullptr;
void(*destroy)(void* ptr) noexcept = nullptr;
Expand Down Expand Up @@ -137,10 +137,20 @@ namespace stx
}

template <typename T>
static void call_thread_op(void* ptr, thread_state state) noexcept
static thread_state call_thread_op(void* ptr, thread_state state) noexcept
{
// Abort and/or join (expected thread_state::aborting or thread_state::finished)
*std::launder(static_cast<T*>(ptr)) = state;

if constexpr (std::is_convertible_v<const T&, thread_state>)
{
return *std::launder(static_cast<T*>(ptr));
}
else
{
constexpr thread_state context_finished{3};
return context_finished;
}
}

template <typename T>
Expand Down
Loading