mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-05 06:26:49 +00:00
Add new typemap for always existing objects
Not to be confused with singletons or global variables.
This commit is contained in:
parent
7db2e2537f
commit
8517ccfdfa
6 changed files with 136 additions and 6 deletions
118
rpcs3/util/fixed_typemap.hpp
Normal file
118
rpcs3/util/fixed_typemap.hpp
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
#include <util/typeindices.hpp>
|
||||
|
||||
namespace stx
|
||||
{
|
||||
// Typemap with exactly one object of each used type, created on init() and destroyed on clear()
|
||||
template <typename /*Tag*/>
|
||||
class manual_fixed_typemap
|
||||
{
|
||||
// Save default constructor and destructor
|
||||
struct typeinfo
|
||||
{
|
||||
void(*create)(void*& ptr) noexcept;
|
||||
void(*destroy)(void*& ptr) noexcept;
|
||||
|
||||
template <typename T>
|
||||
static void call_ctor(void*& ptr) noexcept
|
||||
{
|
||||
// Call default constructor only if available
|
||||
if constexpr (std::is_default_constructible_v<T>)
|
||||
{
|
||||
// Don't overwrite if already exists
|
||||
if (!ptr)
|
||||
{
|
||||
ptr = new T{};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void call_dtor(void*& ptr) noexcept
|
||||
{
|
||||
delete static_cast<T*>(ptr);
|
||||
ptr = nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static typeinfo make_typeinfo()
|
||||
{
|
||||
typeinfo r;
|
||||
r.create = &call_ctor<T>;
|
||||
r.destroy = &call_dtor<T>;
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<void*[]> m_list;
|
||||
|
||||
public:
|
||||
constexpr manual_fixed_typemap() noexcept = default;
|
||||
|
||||
manual_fixed_typemap(const manual_fixed_typemap&) = delete;
|
||||
|
||||
manual_fixed_typemap(manual_fixed_typemap&& r) noexcept
|
||||
{
|
||||
std::swap(m_list, r.m_list);
|
||||
}
|
||||
|
||||
manual_fixed_typemap& operator=(const manual_fixed_typemap&) = delete;
|
||||
|
||||
manual_fixed_typemap& operator=(manual_fixed_typemap&& r) noexcept
|
||||
{
|
||||
manual_fixed_typemap x(std::move(*this));
|
||||
std::swap(m_list, x.m_list);
|
||||
}
|
||||
|
||||
// Destroy all objects and keep them in uninitialized state, must be called first
|
||||
void reset() noexcept
|
||||
{
|
||||
if (!m_list)
|
||||
{
|
||||
m_list = std::make_unique<void*[]>(stx::typeinfo_v<typeinfo>.count());
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& type : stx::typeinfo_v<typeinfo>)
|
||||
{
|
||||
type.destroy(m_list[type.index()]);
|
||||
}
|
||||
}
|
||||
|
||||
// Default initialize all objects if possible and not already initialized
|
||||
void init() noexcept
|
||||
{
|
||||
for (auto& type : stx::typeinfo_v<typeinfo>)
|
||||
{
|
||||
type.create(m_list[type.index()]);
|
||||
}
|
||||
}
|
||||
|
||||
// Explicitly (re)initialize object of type T possibly with dynamic type As and arguments
|
||||
template <typename T, typename As = T, typename... Args>
|
||||
T* init(Args&&... args) noexcept
|
||||
{
|
||||
auto& ptr = m_list[stx::type_counter<typeinfo>::template type<std::decay_t<T>>.index()];
|
||||
|
||||
if (ptr)
|
||||
{
|
||||
delete static_cast<T*>(ptr);
|
||||
}
|
||||
|
||||
auto* obj = static_cast<T*>(new std::decay_t<As>(std::forward<Args>(args)...));
|
||||
ptr = obj;
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Obtain object pointer (the only thread safe function)
|
||||
template <typename T>
|
||||
T* get() const noexcept
|
||||
{
|
||||
return static_cast<T*>(m_list[stx::type_counter<typeinfo>::template type<std::decay_t<T>>.index()]);
|
||||
}
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue