mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
named_thread: fix bugs in std::forward usage
Fix few misused threads and other bugs.
This commit is contained in:
parent
d788b12a8e
commit
bbf52f3cea
@ -2211,8 +2211,16 @@ thread_state thread_ctrl::state()
|
|||||||
{
|
{
|
||||||
auto _this = g_tls_this_thread;
|
auto _this = g_tls_this_thread;
|
||||||
|
|
||||||
|
// Guard for recursive calls (TODO: may be more effective to reuse one of m_sync bits)
|
||||||
|
static thread_local bool s_tls_exec = false;
|
||||||
|
|
||||||
// Drain execution queue
|
// Drain execution queue
|
||||||
|
if (!s_tls_exec)
|
||||||
|
{
|
||||||
|
s_tls_exec = true;
|
||||||
_this->exec();
|
_this->exec();
|
||||||
|
s_tls_exec = false;
|
||||||
|
}
|
||||||
|
|
||||||
return static_cast<thread_state>(_this->m_sync & 3);
|
return static_cast<thread_state>(_this->m_sync & 3);
|
||||||
}
|
}
|
||||||
|
@ -344,6 +344,84 @@ private:
|
|||||||
static const u64 process_affinity_mask;
|
static const u64 process_affinity_mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Used internally
|
||||||
|
template <bool Discard, typename Ctx, typename... Args>
|
||||||
|
class thread_future_t : public thread_future, result_storage<Ctx, std::conditional_t<Discard, int, void>, Args...>
|
||||||
|
{
|
||||||
|
[[no_unique_address]] decltype(std::make_tuple(std::forward<Args>(std::declval<Args>())...)) m_args;
|
||||||
|
|
||||||
|
[[no_unique_address]] Ctx m_func;
|
||||||
|
|
||||||
|
using future = thread_future_t;
|
||||||
|
|
||||||
|
public:
|
||||||
|
thread_future_t(Ctx&& func, Args&&... args)
|
||||||
|
: m_args(std::forward<Args>(args)...)
|
||||||
|
, m_func(std::forward<Ctx>(func))
|
||||||
|
{
|
||||||
|
thread_future::exec.raw() = +[](thread_base* tb, thread_future* tf)
|
||||||
|
{
|
||||||
|
const auto _this = static_cast<future*>(tf);
|
||||||
|
|
||||||
|
if (!tb) [[unlikely]]
|
||||||
|
{
|
||||||
|
if constexpr (!future::empty && !Discard)
|
||||||
|
{
|
||||||
|
_this->init();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (future::empty || Discard)
|
||||||
|
{
|
||||||
|
std::apply(_this->m_func, std::move(_this->m_args));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new (_this->_get()) decltype(auto)(std::apply(_this->m_func, std::move(_this->m_args)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
~thread_future_t()
|
||||||
|
{
|
||||||
|
if constexpr (!future::empty && !Discard)
|
||||||
|
{
|
||||||
|
if (!this->exec)
|
||||||
|
{
|
||||||
|
this->destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decltype(auto) get()
|
||||||
|
{
|
||||||
|
while (this->exec)
|
||||||
|
{
|
||||||
|
this->wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (!future::empty && !Discard)
|
||||||
|
{
|
||||||
|
return *this->_get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decltype(auto) get() const
|
||||||
|
{
|
||||||
|
while (this->exec)
|
||||||
|
{
|
||||||
|
this->wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (!future::empty && !Discard)
|
||||||
|
{
|
||||||
|
return *this->_get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Derived from the callable object Context, possibly a lambda
|
// Derived from the callable object Context, possibly a lambda
|
||||||
template <class Context>
|
template <class Context>
|
||||||
class named_thread final : public Context, result_storage<Context>, thread_base
|
class named_thread final : public Context, result_storage<Context>, thread_base
|
||||||
@ -467,74 +545,9 @@ public:
|
|||||||
|
|
||||||
if constexpr (v1)
|
if constexpr (v1)
|
||||||
{
|
{
|
||||||
class future : public thread_future, result_storage<Context, void, Arg, Args...>
|
using future = thread_future_t<Discard, Context&, Arg, Args...>;
|
||||||
{
|
|
||||||
// A tuple to store arguments
|
|
||||||
decltype(std::make_tuple(std::forward<Arg, Args...>(arg, args...))) m_args;
|
|
||||||
|
|
||||||
public:
|
single_ptr<future> target = make_single<future>(*static_cast<Context*>(this), std::forward<Arg>(arg), std::forward<Args>(args)...);
|
||||||
future(Arg&& arg, Args&&... args)
|
|
||||||
: m_args(std::forward<Arg, Args...>(arg, args...))
|
|
||||||
{
|
|
||||||
thread_future::exec.raw() = +[](thread_base* tb, thread_future* tf)
|
|
||||||
{
|
|
||||||
const auto _this = static_cast<future*>(tf);
|
|
||||||
|
|
||||||
if (!tb) [[unlikely]]
|
|
||||||
{
|
|
||||||
if constexpr (!future::empty && !Discard)
|
|
||||||
{
|
|
||||||
_this->init();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if constexpr (future::empty || Discard)
|
|
||||||
{
|
|
||||||
std::apply(*static_cast<Context*>(static_cast<named_thread*>(tb)), _this->m_args);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
new (_this->_get()) decltype(auto)(std::apply(*static_cast<Context*>(static_cast<named_thread*>(tb)), _this->m_args));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
future(const future&) = delete;
|
|
||||||
|
|
||||||
future& operator=(const future&) = delete;
|
|
||||||
|
|
||||||
~future()
|
|
||||||
{
|
|
||||||
if constexpr (!future::empty && !Discard)
|
|
||||||
{
|
|
||||||
// Should be set to null if executed
|
|
||||||
if (!this->exec)
|
|
||||||
{
|
|
||||||
this->destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
decltype(auto) get()
|
|
||||||
{
|
|
||||||
if constexpr (!future::empty && !Discard)
|
|
||||||
{
|
|
||||||
return *this->_get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
decltype(auto) get() const
|
|
||||||
{
|
|
||||||
if constexpr (!future::empty && !Discard)
|
|
||||||
{
|
|
||||||
return *this->_get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
single_ptr<future> target = make_single<future>(std::forward<Arg, Args...>(arg, args...));
|
|
||||||
|
|
||||||
if constexpr (!Discard)
|
if constexpr (!Discard)
|
||||||
{
|
{
|
||||||
@ -553,75 +566,9 @@ public:
|
|||||||
}
|
}
|
||||||
else if constexpr (v2)
|
else if constexpr (v2)
|
||||||
{
|
{
|
||||||
class future : public thread_future, result_storage<std::decay_t<Arg>, void, Args...>
|
using future = thread_future_t<Discard, Arg, Args...>;
|
||||||
{
|
|
||||||
decltype(std::make_tuple(std::forward<Args...>(args...))) m_args;
|
|
||||||
|
|
||||||
std::decay_t<Arg> m_func;
|
single_ptr<future> target = make_single<future>(std::forward<Arg>(arg), std::forward<Args>(args)...);
|
||||||
|
|
||||||
public:
|
|
||||||
future(Arg func, Args&&... args)
|
|
||||||
: m_args(std::forward<Args...>(args...))
|
|
||||||
, m_func(func)
|
|
||||||
{
|
|
||||||
thread_future::exec.raw() = +[](thread_base* tb, thread_future* tf)
|
|
||||||
{
|
|
||||||
const auto _this = static_cast<future*>(tf);
|
|
||||||
|
|
||||||
if (!tb) [[unlikely]]
|
|
||||||
{
|
|
||||||
if constexpr (!future::empty && !Discard)
|
|
||||||
{
|
|
||||||
_this->init();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if constexpr (future::empty || Discard)
|
|
||||||
{
|
|
||||||
std::apply(_this->m_func, _this->m_args);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
new (_this->_get()) decltype(auto)(std::apply(_this->m_func, _this->m_args));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
future(const future&) = delete;
|
|
||||||
|
|
||||||
future& operator=(const future&) = delete;
|
|
||||||
|
|
||||||
~future()
|
|
||||||
{
|
|
||||||
if constexpr (!future::empty && !Discard)
|
|
||||||
{
|
|
||||||
if (!this->exec)
|
|
||||||
{
|
|
||||||
this->destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
decltype(auto) get()
|
|
||||||
{
|
|
||||||
if constexpr (!future::empty && !Discard)
|
|
||||||
{
|
|
||||||
return *this->_get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
decltype(auto) get() const
|
|
||||||
{
|
|
||||||
if constexpr (!future::empty && !Discard)
|
|
||||||
{
|
|
||||||
return *this->_get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
single_ptr<future> target = make_single<future>(std::forward<Arg, Args...>(arg, args...));
|
|
||||||
|
|
||||||
if constexpr (!Discard)
|
if constexpr (!Discard)
|
||||||
{
|
{
|
||||||
@ -637,75 +584,9 @@ public:
|
|||||||
}
|
}
|
||||||
else if constexpr (v3)
|
else if constexpr (v3)
|
||||||
{
|
{
|
||||||
class future : public thread_future, result_storage<std::decay_t<Arg>, void, Context&, Args...>
|
using future = thread_future_t<Discard, Arg, Context&, Args...>;
|
||||||
{
|
|
||||||
decltype(std::make_tuple(std::forward<Args...>(args...))) m_args;
|
|
||||||
|
|
||||||
std::decay_t<Arg> m_func;
|
single_ptr<future> target = make_single<future>(std::forward<Arg>(arg), std::ref(*static_cast<Context*>(this)), std::forward<Args>(args)...);
|
||||||
|
|
||||||
public:
|
|
||||||
future(Arg func, Args&&... args)
|
|
||||||
: m_args(std::forward<Args...>(args...))
|
|
||||||
, m_func(func)
|
|
||||||
{
|
|
||||||
thread_future::exec.raw() = +[](thread_base* tb, thread_future* tf)
|
|
||||||
{
|
|
||||||
const auto _this = static_cast<future*>(tf);
|
|
||||||
|
|
||||||
if (!tb) [[unlikely]]
|
|
||||||
{
|
|
||||||
if constexpr (!future::empty && !Discard)
|
|
||||||
{
|
|
||||||
_this->init();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if constexpr (future::empty || Discard)
|
|
||||||
{
|
|
||||||
std::apply(_this->m_func, *static_cast<Context*>(static_cast<named_thread*>(tb)), _this->m_args);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
new (_this->_get()) decltype(auto)(std::apply(_this->m_func, *static_cast<Context*>(static_cast<named_thread*>(tb)), _this->m_args));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
future(const future&) = delete;
|
|
||||||
|
|
||||||
future& operator=(const future&) = delete;
|
|
||||||
|
|
||||||
~future()
|
|
||||||
{
|
|
||||||
if constexpr (!future::empty && !Discard)
|
|
||||||
{
|
|
||||||
if (!this->exec)
|
|
||||||
{
|
|
||||||
this->destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
decltype(auto) get()
|
|
||||||
{
|
|
||||||
if constexpr (!future::empty && !Discard)
|
|
||||||
{
|
|
||||||
return *this->_get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
decltype(auto) get() const
|
|
||||||
{
|
|
||||||
if constexpr (!future::empty && !Discard)
|
|
||||||
{
|
|
||||||
return *this->_get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
single_ptr<future> target = make_single<future>(std::forward<Arg, Args...>(arg, args...));
|
|
||||||
|
|
||||||
if constexpr (!Discard)
|
if constexpr (!Discard)
|
||||||
{
|
{
|
||||||
|
@ -166,6 +166,11 @@ namespace rsx
|
|||||||
close(true, true);
|
close(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct msg_dialog_thread
|
||||||
|
{
|
||||||
|
static constexpr auto thread_name = "MsgDialog Thread"sv;
|
||||||
|
};
|
||||||
|
|
||||||
error_code message_dialog::show(bool is_blocking, const std::string& text, const MsgDialogType& type, std::function<void(s32 status)> on_close)
|
error_code message_dialog::show(bool is_blocking, const std::string& text, const MsgDialogType& type, std::function<void(s32 status)> on_close)
|
||||||
{
|
{
|
||||||
visible = false;
|
visible = false;
|
||||||
@ -246,7 +251,7 @@ namespace rsx
|
|||||||
{
|
{
|
||||||
if (!exit)
|
if (!exit)
|
||||||
{
|
{
|
||||||
g_fxo->init<named_thread>("MsgDialog Thread", [&, tbit = alloc_thread_bit()]()
|
g_fxo->get<named_thread<msg_dialog_thread>>()->operator()([&, tbit = alloc_thread_bit()]()
|
||||||
{
|
{
|
||||||
g_thread_bit = tbit;
|
g_thread_bit = tbit;
|
||||||
|
|
||||||
|
@ -781,6 +781,11 @@ namespace rsx
|
|||||||
return m_cached_resource;
|
return m_cached_resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct osk_dialog_thread
|
||||||
|
{
|
||||||
|
static constexpr auto thread_name = "OSK Thread"sv;
|
||||||
|
};
|
||||||
|
|
||||||
void osk_dialog::Create(const std::string& title, const std::u16string& message, char16_t* init_text, u32 charlimit, u32 prohibit_flags, u32 panel_flag, u32 first_view_panel)
|
void osk_dialog::Create(const std::string& title, const std::u16string& message, char16_t* init_text, u32 charlimit, u32 prohibit_flags, u32 panel_flag, u32 first_view_panel)
|
||||||
{
|
{
|
||||||
state = OskDialogState::Open;
|
state = OskDialogState::Open;
|
||||||
@ -1012,7 +1017,7 @@ namespace rsx
|
|||||||
|
|
||||||
update_panel();
|
update_panel();
|
||||||
|
|
||||||
g_fxo->init<named_thread>("OSK Thread", [this, tbit = alloc_thread_bit()]
|
g_fxo->get<named_thread<osk_dialog_thread>>()->operator()([this, tbit = alloc_thread_bit()]
|
||||||
{
|
{
|
||||||
g_thread_bit = tbit;
|
g_thread_bit = tbit;
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ namespace stx
|
|||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#pragma GCC diagnostic ignored "-Wundefined-var-template"
|
#pragma GCC diagnostic ignored "-Wundefined-var-template"
|
||||||
|
#pragma GCC diagnostic ignored "-Wundefined-internal"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ namespace stx
|
|||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
constexpr bool is_same_ptr() noexcept
|
constexpr bool is_same_ptr() noexcept
|
||||||
{
|
{
|
||||||
#if !defined(_MSC_VER) && !defined(__clang__)
|
#ifdef _MSC_VER
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
if constexpr (std::is_void_v<T> || std::is_void_v<U> || std::is_same_v<T, U>)
|
if constexpr (std::is_void_v<T> || std::is_void_v<U> || std::is_same_v<T, U>)
|
||||||
@ -30,14 +31,14 @@ namespace stx
|
|||||||
}
|
}
|
||||||
else if constexpr (std::is_convertible_v<U*, T*>)
|
else if constexpr (std::is_convertible_v<U*, T*>)
|
||||||
{
|
{
|
||||||
const auto u = std::addressof(sample<U>);
|
constexpr auto u = std::addressof(sample<U>);
|
||||||
const volatile void* x = u;
|
constexpr volatile void* x = u;
|
||||||
return static_cast<T*>(u) == x;
|
return static_cast<T*>(u) == x;
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_convertible_v<T*, U*>)
|
else if constexpr (std::is_convertible_v<T*, U*>)
|
||||||
{
|
{
|
||||||
const auto t = std::addressof(sample<T>);
|
constexpr auto t = std::addressof(sample<T>);
|
||||||
const volatile void* x = t;
|
constexpr volatile void* x = t;
|
||||||
return static_cast<U*>(t) == x;
|
return static_cast<U*>(t) == x;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
Loading…
Reference in New Issue
Block a user