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:
parent
388ca1c645
commit
7db6594358
@ -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)
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user