Postpone thread launching on g_fxo->init

This commit is contained in:
Eladash 2023-12-14 22:20:21 +02:00 committed by Elad Ashkenazi
parent a4bcba8971
commit 0c410f8a14
11 changed files with 112 additions and 44 deletions

View file

@ -15,6 +15,8 @@ extern thread_local std::string_view g_tls_serialize_name;
namespace stx
{
struct launch_retainer{};
// Simplified typemap with exactly one object of each used type, non-moveable. Initialized on init(). Destroyed on clear().
template <typename Tag /*Tag should be unique*/, u32 Size = 0, u32 Align = (Size ? 64 : __STDCPP_DEFAULT_NEW_ALIGNMENT__)>
class alignas(Align) manual_typemap
@ -62,7 +64,7 @@ namespace stx
struct typeinfo
{
bool(*create)(uchar* ptr, manual_typemap&, utils::serial*, std::string_view) noexcept = nullptr;
void(*stop)(void* ptr, thread_state) noexcept = nullptr;
void(*thread_op)(void* ptr, thread_state) noexcept = nullptr;
void(*save)(void* ptr, utils::serial&) noexcept = nullptr;
void(*destroy)(void* ptr) noexcept = nullptr;
std::string_view name;
@ -72,13 +74,19 @@ namespace stx
{
if (ar)
{
if constexpr (std::is_constructible_v<T, manual_typemap&, exact_t<utils::serial&>>)
if constexpr (std::is_constructible_v<T, exact_t<manual_typemap&>, exact_t<utils::serial&>>)
{
g_tls_serialize_name = name;
new (ptr) T(_this, exact_t<utils::serial&>(*ar));
return true;
}
if constexpr (std::is_constructible_v<T, exact_t<const launch_retainer&>, exact_t<utils::serial&>>)
{
new (ptr) T(exact_t<const launch_retainer&>(launch_retainer{}), exact_t<utils::serial&>(*ar));
return true;
}
if constexpr (std::is_constructible_v<T, exact_t<utils::serial&>>)
{
g_tls_serialize_name = name;
@ -88,12 +96,18 @@ namespace stx
}
// Allow passing reference to "this"
if constexpr (std::is_constructible_v<T, manual_typemap&>)
if constexpr (std::is_constructible_v<T, exact_t<manual_typemap&>>)
{
new (ptr) T(_this);
return true;
}
if constexpr (std::is_constructible_v<T, exact_t<const launch_retainer&>>)
{
new (ptr) T(exact_t<const launch_retainer&>(launch_retainer{}));
return true;
}
// Call default constructor only if available
if constexpr (std::is_default_constructible_v<T>)
{
@ -111,7 +125,7 @@ namespace stx
}
template <typename T>
static void call_stop(void* ptr, thread_state state) noexcept
static void 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;
@ -134,7 +148,7 @@ namespace stx
if constexpr (std::is_assignable_v<T&, thread_state>)
{
r.stop = &call_stop<T>;
r.thread_op = &call_thread_op<T>;
}
if constexpr (!!(requires (T& a) { a.save(std::declval<stx::exact_t<utils::serial&>>()); }))
@ -233,6 +247,8 @@ namespace stx
return a.first < b.first;
});
const auto info_before = m_info;
for (pos = 0; pos < stx::typelist<typeinfo>().count(); pos++)
{
const auto& type = *order[pos].second;
@ -260,6 +276,15 @@ namespace stx
}
}
// Launch threads
for (auto it = m_info; it != info_before; it--)
{
if (auto op = (*std::prev(it))->thread_op)
{
op(*std::prev(m_order, m_info - it + 1), thread_state{});
}
}
g_tls_serialize_name = {};
}

View file

@ -1174,13 +1174,21 @@ namespace stx
template <typename T>
struct exact_t
{
static_assert(std::is_reference_v<T> || std::is_convertible_v<T, const T&>);
T obj;
exact_t(T&& _obj) : obj(std::forward<T>(_obj)) {}
explicit exact_t(T&& _obj) : obj(std::forward<T>(_obj)) {}
exact_t& operator=(const exact_t&) = delete;
// TODO: More conversions
template <typename U> requires (std::is_same_v<U&, T>)
operator U&() const { return obj; };
operator U&() const noexcept { return obj; };
template <typename U> requires (std::is_same_v<const U&, T>)
operator const U&() const noexcept { return obj; };
template <typename U> requires (std::is_same_v<U, T> && std::is_copy_constructible_v<T>)
operator U() const noexcept { return obj; };
};
}