1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 10:42:36 +01:00

rsx/overlays: Use lf_queue for a lock-free stack implementation

This commit is contained in:
kd-11 2023-02-14 02:27:47 +03:00 committed by kd-11
parent 388ca1c645
commit 7db6594358
4 changed files with 34 additions and 50 deletions

View File

@ -359,6 +359,14 @@ public:
return result; return result;
} }
// Withdraw the list in reverse order (LIFO/FILO)
lf_queue_slice<T> pop_all_reversed()
{
lf_queue_slice<T> result;
result.m_head = m_head.exchange(nullptr);
return result;
}
// Apply func(data) to each element, return the total length // Apply func(data) to each element, return the total length
template <typename F> template <typename F>
usz apply(F func) usz apply(F func)

View File

@ -7,6 +7,15 @@ namespace rsx
{ {
namespace overlays namespace overlays
{ {
display_manager::display_manager(int)
{
m_input_thread = std::make_shared<named_thread<overlay_input_thread>>();
(*m_input_thread)([this]()
{
input_thread_loop();
});
}
display_manager::~display_manager() display_manager::~display_manager()
{ {
if (m_input_thread) if (m_input_thread)
@ -135,22 +144,9 @@ namespace rsx
m_type_ids_to_remove.clear(); m_type_ids_to_remove.clear();
} }
void display_manager::on_overlay_activated(const std::shared_ptr<overlay>& item) void display_manager::on_overlay_activated(const std::shared_ptr<overlay>& /*item*/)
{ {
if (auto iface = std::dynamic_pointer_cast<user_interface>(item)) // TODO: Internal management, callbacks, etc
{
// Kick input thread if not enabled. Expect the interface to attach shortly
std::lock_guard lock(m_input_thread_lock);
if (!m_input_thread)
{
m_input_thread = std::make_shared<named_thread<overlay_input_thread>>();
(*m_input_thread)([this]()
{
input_thread_loop();
});
}
}
} }
void display_manager::attach_thread_input( void display_manager::attach_thread_input(
@ -161,8 +157,7 @@ namespace rsx
{ {
if (auto iface = std::dynamic_pointer_cast<user_interface>(get(uid))) if (auto iface = std::dynamic_pointer_cast<user_interface>(get(uid)))
{ {
std::lock_guard lock(m_input_thread_lock); m_input_token_stack.push(
m_input_token_stack.emplace_front(
std::move(iface), std::move(iface),
on_input_loop_enter, on_input_loop_enter,
on_input_loop_exit, on_input_loop_exit,
@ -172,46 +167,27 @@ namespace rsx
void display_manager::on_overlay_removed(const std::shared_ptr<overlay>& item) void display_manager::on_overlay_removed(const std::shared_ptr<overlay>& item)
{ {
if (!dynamic_cast<user_interface*>(item.get())) auto iface = std::dynamic_pointer_cast<user_interface>(item);
if (!iface)
{ {
// Not instance of UI, ignore // Not instance of UI, ignore
return; return;
} }
std::lock_guard lock(m_input_thread_lock); iface->detach_input();
for (auto& entry : m_input_token_stack)
{
if (entry.target->uid == item->uid)
{
// Release
entry.target = {};
break;
}
}
// The top must never be an empty ref. Pop all empties.
while (!m_input_token_stack.empty() && !m_input_token_stack.front().target)
{
m_input_token_stack.pop_front();
}
} }
void display_manager::input_thread_loop() void display_manager::input_thread_loop()
{ {
while (!m_input_thread_abort) while (!m_input_thread_abort)
{ {
input_thread_context_t input_context; for (auto&& input_context : m_input_token_stack.pop_all_reversed())
{ {
reader_lock lock(m_input_thread_lock); if (input_context.target->is_detached())
if (!m_input_token_stack.empty())
{ {
input_context = m_input_token_stack.front(); continue;
m_input_token_stack.pop_front();
} }
}
if (input_context.target)
{
if (input_context.input_loop_prologue) if (input_context.input_loop_prologue)
{ {
input_context.input_loop_prologue(); input_context.input_loop_prologue();
@ -236,10 +212,8 @@ namespace rsx
rsx_log.error("Input loop exited with error code=%d", result); rsx_log.error("Input loop exited with error code=%d", result);
} }
} }
else
{ m_input_token_stack.wait();
thread_ctrl::wait_for(1000);
}
} }
} }
} }

View File

@ -39,8 +39,7 @@ namespace rsx
public: public:
// Disable default construction to make it conditionally available in g_fxo // Disable default construction to make it conditionally available in g_fxo
explicit display_manager(int) noexcept explicit display_manager(int) noexcept;
{}
~display_manager(); ~display_manager();
@ -176,8 +175,7 @@ namespace rsx
std::function<s32()> input_loop_override = nullptr; std::function<s32()> input_loop_override = nullptr;
}; };
std::deque<input_thread_context_t> m_input_token_stack; lf_queue<input_thread_context_t> m_input_token_stack;
shared_mutex m_input_thread_lock;
atomic_t<bool> m_input_thread_abort = false; atomic_t<bool> m_input_thread_abort = false;
std::shared_ptr<named_thread<overlay_input_thread>> m_input_thread; std::shared_ptr<named_thread<overlay_input_thread>> m_input_thread;

View File

@ -112,6 +112,7 @@ namespace rsx
atomic_t<bool> m_interactive = false; atomic_t<bool> m_interactive = false;
bool m_start_pad_interception = true; bool m_start_pad_interception = true;
atomic_t<bool> m_stop_pad_interception = false; atomic_t<bool> m_stop_pad_interception = false;
atomic_t<bool> m_input_thread_detached = false;
atomic_t<u64> thread_bits = 0; atomic_t<u64> thread_bits = 0;
bool m_keyboard_input_enabled = false; // Allow keyboard input bool m_keyboard_input_enabled = false; // Allow keyboard input
bool m_keyboard_pad_handler_active = true; // Initialized as true to prevent keyboard input until proven otherwise. bool m_keyboard_pad_handler_active = true; // Initialized as true to prevent keyboard input until proven otherwise.
@ -146,6 +147,9 @@ namespace rsx
public: public:
s32 return_code = 0; // CELL_OK s32 return_code = 0; // CELL_OK
bool is_detached() const { return m_input_thread_detached; }
void detach_input() { m_input_thread_detached.store(true); }
void update() override {} void update() override {}
compiled_resource get_compiled() override = 0; compiled_resource get_compiled() override = 0;