...
This commit is contained in:
139
source/opengl/resource_management/resource_manager.ipp
Normal file
139
source/opengl/resource_management/resource_manager.ipp
Normal 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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user