1#ifndef LIBSBX_GRAPHICS_RESOURSE_STORAGE_HPP_
2#define LIBSBX_GRAPHICS_RESOURSE_STORAGE_HPP_
6#include <unordered_set>
10#include <libsbx/utility/assert.hpp>
12#include <libsbx/memory/aligned_storage.hpp>
14namespace sbx::graphics {
16template<
typename Type>
23 inline static constexpr auto invalid = std::uint32_t{0xFFFFFFFF};
29 constexpr resource_handle(
const std::uint32_t handle,
const std::uint32_t generation)
31 _generation{generation} { }
33 constexpr auto handle()
const noexcept -> std::uint32_t {
37 constexpr auto generation()
const noexcept -> std::uint32_t {
41 constexpr auto operator==(
const resource_handle& other)
const noexcept ->
bool {
42 return _handle == other._handle && _generation == other._generation;
45 constexpr auto is_valid()
const noexcept ->
bool {
46 return _handle != invalid;
49 constexpr operator bool()
const noexcept {
55 std::uint32_t _handle;
56 std::uint32_t _generation;
61 std::filesystem::path path;
64template<
typename Type>
69 using value_type = Type;
70 using size_type = std::size_t;
74 _storage.reserve(32u);
75 _generations.reserve(32u);
76 _free_handles.reserve(32u);
87 template<
typename... Args>
88 requires (std::is_constructible_v<value_type, Args...>)
90 if (!_free_handles.empty()) {
91 const auto handle = _free_handles.back();
92 _free_handles.pop_back();
94 std::construct_at(_ptr(handle), std::forward<Args>(args)...);
96 const auto generation = ++_generations[handle];
101 const auto handle =
static_cast<std::uint32_t
>(_storage.size());
103 _storage.emplace_back();
104 std::construct_at(_ptr(handle), std::forward<Args>(args)...);
106 _generations.push_back(0u);
111 auto get(
const handle_type& handle) -> value_type& {
112 utility::assert_that(handle.handle() < _storage.size(),
"Handle is out of bounds");
113 utility::assert_that(handle.generation() == _generations[handle.handle()],
"Handle generation does not match");
115 return *_ptr(handle.handle());
118 auto get(
const handle_type& handle)
const ->
const value_type& {
119 utility::assert_that(handle.handle() < _storage.size(),
"Handle is out of bounds");
120 utility::assert_that(handle.generation() == _generations[handle.handle()],
"Handle generation does not match");
122 return *_ptr(handle.handle());
126 utility::assert_that(handle.handle() < _storage.size(),
"Handle is out of bounds");
127 utility::assert_that(handle.generation() == _generations[handle.handle()],
"Handle generation does not match");
129 std::destroy_at(_ptr(handle.handle()));
130 _free_handles.push_back(handle.handle());
133 auto clear() ->
void {
134 auto free_list = std::unordered_set<std::uint32_t>{_free_handles.begin(), _free_handles.end()};
136 for (std::uint32_t i = 0; i < _storage.size(); ++i) {
137 if (free_list.contains(i)) {
141 std::destroy_at(_ptr(i));
145 _generations.clear();
146 _free_handles.clear();
151 auto _ptr(
const size_type index) -> value_type* {
152 return std::launder(
reinterpret_cast<value_type*
>(_storage.data() + index));
155 auto _ptr(
const size_type index)
const ->
const value_type* {
156 return std::launder(
reinterpret_cast<const value_type*
>(_storage.data() + index));
159 std::vector<memory::storage_for_t<value_type>> _storage;
160 std::vector<std::uint32_t> _generations;
161 std::vector<std::uint32_t> _free_handles;
167template<
typename Type>
168struct std::hash<sbx::graphics::resource_handle<Type>> {
171 auto hash = std::size_t{};
173 sbx::utility::hash_combine(hash, handle.handle(), handle.generation());
Definition: resource_storage.hpp:17
Definition: resource_storage.hpp:65