mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-10 17:01:24 +12:00
g_fxo: destroy objects in reverse creation order
Maintain creation order internally.
This commit is contained in:
parent
6a443c0fbd
commit
9ae08946ac
1 changed files with 59 additions and 2 deletions
|
@ -3,6 +3,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <algorithm>
|
||||||
#include <util/typeindices.hpp>
|
#include <util/typeindices.hpp>
|
||||||
|
|
||||||
namespace stx
|
namespace stx
|
||||||
|
@ -50,6 +51,9 @@ namespace stx
|
||||||
|
|
||||||
std::unique_ptr<void*[]> m_list;
|
std::unique_ptr<void*[]> m_list;
|
||||||
|
|
||||||
|
std::unique_ptr<unsigned long long[]> m_order;
|
||||||
|
unsigned long long m_init_count = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr manual_fixed_typemap() noexcept = default;
|
constexpr manual_fixed_typemap() noexcept = default;
|
||||||
|
|
||||||
|
@ -58,6 +62,8 @@ namespace stx
|
||||||
manual_fixed_typemap(manual_fixed_typemap&& r) noexcept
|
manual_fixed_typemap(manual_fixed_typemap&& r) noexcept
|
||||||
{
|
{
|
||||||
std::swap(m_list, r.m_list);
|
std::swap(m_list, r.m_list);
|
||||||
|
std::swap(m_order, r.m_order);
|
||||||
|
std::swap(m_init_count, r.m_init_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
manual_fixed_typemap& operator=(const manual_fixed_typemap&) = delete;
|
manual_fixed_typemap& operator=(const manual_fixed_typemap&) = delete;
|
||||||
|
@ -66,20 +72,64 @@ namespace stx
|
||||||
{
|
{
|
||||||
manual_fixed_typemap x(std::move(*this));
|
manual_fixed_typemap x(std::move(*this));
|
||||||
std::swap(m_list, x.m_list);
|
std::swap(m_list, x.m_list);
|
||||||
|
std::swap(m_order, x.m_order);
|
||||||
|
std::swap(m_init_count, x.m_init_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy all objects and keep them in uninitialized state, must be called first
|
// Destroy all objects and keep them in uninitialized state, must be called first
|
||||||
void reset() noexcept
|
void reset() noexcept
|
||||||
{
|
{
|
||||||
|
const auto total_count = stx::typelist_v<typeinfo>.count();
|
||||||
|
|
||||||
if (!m_list)
|
if (!m_list)
|
||||||
{
|
{
|
||||||
m_list = std::make_unique<void*[]>(stx::typelist_v<typeinfo>.count());
|
m_list = std::make_unique<void*[]>(total_count);
|
||||||
|
m_order = std::make_unique<unsigned long long[]>(total_count);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Destroy list element
|
||||||
|
struct destroy_info
|
||||||
|
{
|
||||||
|
void** object_pointer;
|
||||||
|
unsigned long long created;
|
||||||
|
void(*destroy)(void*& ptr) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto all_data = std::make_unique<destroy_info[]>(stx::typelist_v<typeinfo>.count());
|
||||||
|
|
||||||
|
// Actual number of created objects
|
||||||
|
unsigned _max = 0;
|
||||||
|
|
||||||
|
// Create destroy list
|
||||||
for (auto& type : stx::typelist_v<typeinfo>)
|
for (auto& type : stx::typelist_v<typeinfo>)
|
||||||
{
|
{
|
||||||
type.destroy(m_list[type.index()]);
|
if (m_order[type.index()] == 0)
|
||||||
|
{
|
||||||
|
// Skip object if not created
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
all_data[_max].object_pointer = &m_list[type.index()];
|
||||||
|
all_data[_max].created = m_order[type.index()];
|
||||||
|
all_data[_max].destroy = type.destroy;
|
||||||
|
|
||||||
|
// Clear creation order
|
||||||
|
m_order[type.index()] = 0;
|
||||||
|
_max++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort destroy list according to absolute creation order
|
||||||
|
std::sort(all_data.get(), all_data.get() + _max, [](const destroy_info& a, const destroy_info& b)
|
||||||
|
{
|
||||||
|
// Destroy order is the inverse of creation order
|
||||||
|
return a.created > b.created;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Destroy objects in correct order
|
||||||
|
for (unsigned i = 0; i < _max; i++)
|
||||||
|
{
|
||||||
|
all_data[i].destroy(*all_data[i].object_pointer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,6 +139,12 @@ namespace stx
|
||||||
for (auto& type : stx::typelist_v<typeinfo>)
|
for (auto& type : stx::typelist_v<typeinfo>)
|
||||||
{
|
{
|
||||||
type.create(m_list[type.index()]);
|
type.create(m_list[type.index()]);
|
||||||
|
|
||||||
|
// Allocate initialization order id
|
||||||
|
if (m_list[type.index()])
|
||||||
|
{
|
||||||
|
m_order[type.index()] = ++m_init_count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,6 +160,7 @@ namespace stx
|
||||||
}
|
}
|
||||||
|
|
||||||
As* obj = new std::decay_t<As>(std::forward<Args>(args)...);
|
As* obj = new std::decay_t<As>(std::forward<Args>(args)...);
|
||||||
|
m_order[stx::typeindex<typeinfo, std::decay_t<T>>()] = ++m_init_count;
|
||||||
ptr = static_cast<T*>(obj);
|
ptr = static_cast<T*>(obj);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue