Add new typemap for always existing objects

Not to be confused with singletons or global variables.
This commit is contained in:
Nekotekina 2019-08-20 04:49:22 +03:00
parent 7db2e2537f
commit 8517ccfdfa
6 changed files with 136 additions and 6 deletions

View file

@ -41,7 +41,7 @@ void spu_recompiler::init()
if (!m_spurt)
{
m_cache = fxm::get<spu_cache>();
m_spurt = fxm::get_always<spu_runtime>();
m_spurt = g_fxo->get<spu_runtime>();
}
}

View file

@ -538,8 +538,6 @@ spu_runtime::spu_runtime()
fs::file(m_cache_path + "spu.log", fs::rewrite);
fs::file(m_cache_path + "spu-ir.log", fs::rewrite);
}
LOG_SUCCESS(SPU, "SPU Recompiler Runtime initialized...");
}
bool spu_runtime::add(u64 last_reset_count, void* _where, spu_function_t compiled)
@ -4165,7 +4163,7 @@ public:
if (!m_spurt)
{
m_cache = fxm::get<spu_cache>();
m_spurt = fxm::get_always<spu_runtime>();
m_spurt = g_fxo->get<spu_runtime>();
cpu_translator::initialize(m_jit.get_context(), m_jit.get_engine());
const auto md_name = llvm::MDString::get(m_context, "branch_weights");

View file

@ -76,6 +76,10 @@ public:
public:
spu_runtime();
spu_runtime(const spu_runtime&) = delete;
spu_runtime& operator=(const spu_runtime&) = delete;
const std::string& get_cache_path() const
{
return m_cache_path;
@ -226,7 +230,7 @@ public:
};
protected:
std::shared_ptr<spu_runtime> m_spurt;
spu_runtime* m_spurt{};
u32 m_pos;
u32 m_size;

View file

@ -138,7 +138,7 @@ class idm
{
using traits = id_manager::id_traits<T>;
// Note: if id is lower than base, diff / step will be higher than count
// Note: if id is lower than base, diff / step will be higher than count
u32 diff = id - traits::base;
if (diff % traits::step)
@ -785,6 +785,7 @@ public:
};
#include "Utilities/typemap.h"
#include "util/fixed_typemap.hpp"
extern utils::typemap g_typemap;
@ -793,3 +794,7 @@ constexpr utils::typemap* g_idm = &g_typemap;
using utils::id_new;
using utils::id_any;
using utils::id_always;
extern stx::manual_fixed_typemap<void> g_fixed_typemap;
constexpr stx::manual_fixed_typemap<void>* g_fxo = &g_fixed_typemap;

View file

@ -46,6 +46,8 @@
#include "Emu/RSX/VK/VulkanAPI.h"
#endif
stx::manual_fixed_typemap<void> g_fixed_typemap;
utils::typemap g_typemap{nullptr};
cfg_root g_cfg;
@ -318,6 +320,7 @@ void Emulator::Init()
idm::init();
fxm::init();
g_idm->init();
g_fxo->reset();
// Reset defaults, cache them
g_cfg.from_default();
@ -1511,6 +1514,7 @@ void Emulator::Load(const std::string& title_id, bool add_only, bool force_globa
LOG_NOTICE(LOADER, "Cache: %s", _main->cache);
}
g_fxo->init();
fxm::import<GSRender>(Emu.GetCallbacks().get_gs_render); // TODO: must be created in appropriate sys_rsx syscall
fxm::import<pad_thread>(Emu.GetCallbacks().get_pad_handler, m_title_id);
network_thread_init();
@ -1735,6 +1739,7 @@ void Emulator::Stop(bool restart)
idm::clear();
fxm::clear();
g_idm->init();
g_fxo->reset();
LOG_NOTICE(GENERAL, "Objects cleared...");

View 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()]);
}
};
}