This commit is contained in:
ZY4N
2025-03-23 21:11:22 +01:00
parent 510398423a
commit c609d49f0d
49 changed files with 1412 additions and 924 deletions

View File

@@ -0,0 +1,67 @@
#ifndef INCLUDE_RESOURCE_HANDLE_IMPLEMENTATION
# error Never include this file directly include 'resource_handle.hpp'
#endif
zgl::resource_handle::resource_handle(id_type id, reference_counter* manager)
: m_id{ id }, m_counter{ manager } {}
zgl::resource_handle::resource_handle(const resource_handle& other) noexcept
: m_id{ other.m_id }, m_counter{ other.m_counter }
{
if (m_id != 0 and m_counter != nullptr)
{
m_counter->add_reference(m_id);
}
}
zgl::resource_handle& zgl::resource_handle::operator=(
const resource_handle& other
) noexcept {
if (&other != this)
{
this->~resource_handle();
m_id = other.m_id;
m_counter = other.m_counter;
if (m_id != 0 and m_counter != nullptr)
{
m_counter->add_reference(m_id);
}
}
return *this;
}
zgl::resource_handle::resource_handle(resource_handle&& other) noexcept
: m_id{ other.m_id }, m_counter{ other.m_counter }
{
other.m_id = 0;
other.m_counter = nullptr;
}
zgl::resource_handle& zgl::resource_handle::resource_handle::operator=(
resource_handle&& other
) noexcept {
if (&other != this)
{
this->~resource_handle();
m_id = other.m_id;
m_counter = other.m_counter;
other.m_id = 0;
other.m_counter = nullptr;
}
return *this;
}
zgl::resource_handle::~resource_handle()
{
if (m_id != 0 and m_counter != nullptr)
{
m_counter->remove_reference(m_id);
}
}

View File

@@ -0,0 +1,139 @@
#ifndef INCLUDE_RESOURCE_MANAGER_IMPLEMENTATION
# error Never include this file directly include 'resource_manager.hpp'
#endif
#include <ranges>
template<typename StoreID, typename MetaData>
bool zgl::resource_manager<StoreID, MetaData>::has_resource(StoreID store_id)
{
std::shared_lock lock(m_lock);
return m_resource_lookup.contains(store_id);
}
template<typename StoreID, typename MetaData>
void zgl::resource_manager<StoreID, MetaData>::add_resource(StoreID store_id, gl_id_type gl_id, MetaData meta)
{
std::unique_lock lock(m_lock);
m_resource_lookup.emplace(store_id, { gl_id, std::move(meta) });
m_reference_counters.emplace(gl_id, 1);
}
template<typename StoreID, typename MetaData>
std::optional<std::pair<zgl::resource_handle, MetaData>> zgl::resource_manager<StoreID, MetaData>::get_resource(
StoreID store_id
) {
std::unique_lock lock(m_lock);
const auto resource_it = m_resource_lookup.find(store_id);
if (resource_it == m_resource_lookup.end())
{
return std::nullopt;
}
const auto gl_id = resource_it.first;
auto [ counter_it, inserted ] = m_reference_counters.try_emplace(gl_id, 0);
++counter_it->second;
return std::pair{ resource_handle(gl_id, this), resource_it->second };
}
template<typename StoreID, typename MetaData>
void zgl::resource_manager<StoreID, MetaData>::collect_garbage()
{
std::unique_lock lock(m_lock);
for (auto& counter : m_reference_counters | std::ranges::views::values)
{
if (counter & unused_resource_flag)
{
const auto value = counter & ~unused_resource_flag;
counter = (value + 1) | unused_resource_flag;
}
}
std::erase_if(
m_reference_counters,
[&](const auto& entry)
{
auto& counter = entry.second;
const auto value = counter & ~unused_resource_flag;
if (value == counter) // Still in use
{
return false;
}
if (value < max_unused_collection_cycle_count)
{
counter = (value + 1) | unused_resource_flag;
return false;
}
m_unused_handles.emplace(entry.first);
return true;
}
);
std::erase_if(
m_resource_lookup,
[&](const auto& entry)
{
return m_unused_handles.contains(entry.second);
}
);
}
template<typename StoreID, typename MetaData>
void zgl::resource_manager<StoreID, MetaData>::add_reference(const gl_id_type id)
{
std::unique_lock lock(m_lock);
auto [it, inserted] = m_reference_counters.try_emplace(id, 0);
++it->second;
}
template<typename StoreID, typename MetaData>
void zgl::resource_manager<StoreID, MetaData>::remove_reference(const gl_id_type id)
{
std::unique_lock lock(m_lock);
if (const auto it = m_reference_counters.find(id); it != m_reference_counters.end())
{
if (it->second == 1)
{
it->second = unused_resource_flag;
}
}
}
template<typename StoreID, typename MetaData>
typename zgl::resource_manager<StoreID, MetaData>::size_type zgl::resource_manager<StoreID, MetaData>::count_garbage()
{
std::shared_lock lock(m_lock);
return m_unused_handles.size();
}
template<typename StoreID, typename MetaData>
void zgl::resource_manager<StoreID, MetaData>::extract_garbage(
std::vector<gl_id_type>& dst
) {
{
std::shared_lock lock(m_lock);
dst.reserve(m_unused_handles.size());
}
{
std::unique_lock lock(m_lock);
dst.resize(m_unused_handles.size());
std::ranges::copy(m_unused_handles, dst.begin());
m_unused_handles.clear();
}
}