sandbox
Loading...
Searching...
No Matches
resource_storage.hpp
1#ifndef LIBSBX_GRAPHICS_RESOURSE_STORAGE_HPP_
2#define LIBSBX_GRAPHICS_RESOURSE_STORAGE_HPP_
3
4#include <vector>
5#include <memory>
6#include <unordered_set>
7#include <filesystem>
8
10#include <libsbx/utility/assert.hpp>
11
12#include <libsbx/memory/aligned_storage.hpp>
13
14namespace sbx::graphics {
15
16template<typename Type>
18
19public:
20
21 using type = Type;
22
23 inline static constexpr auto invalid = std::uint32_t{0xFFFFFFFF};
24
25 constexpr resource_handle()
26 : _handle{invalid},
27 _generation{0} { }
28
29 constexpr resource_handle(const std::uint32_t handle, const std::uint32_t generation)
30 : _handle{handle},
31 _generation{generation} { }
32
33 constexpr auto handle() const noexcept -> std::uint32_t {
34 return _handle;
35 }
36
37 constexpr auto generation() const noexcept -> std::uint32_t {
38 return _generation;
39 }
40
41 constexpr auto operator==(const resource_handle& other) const noexcept -> bool {
42 return _handle == other._handle && _generation == other._generation;
43 }
44
45 constexpr auto is_valid() const noexcept -> bool {
46 return _handle != invalid;
47 }
48
49 constexpr operator bool() const noexcept {
50 return is_valid();
51 }
52
53private:
54
55 std::uint32_t _handle;
56 std::uint32_t _generation;
57
58}; // class resource_handle
59
61 std::filesystem::path path;
62}; // struct resource_metadata
63
64template<typename Type>
66
67public:
68
69 using value_type = Type;
70 using size_type = std::size_t;
72
74 _storage.reserve(32u);
75 _generations.reserve(32u);
76 _free_handles.reserve(32u);
77 }
78
79 resource_storage(const resource_storage& other) = delete;
80
82 clear();
83 }
84
85 auto operator=(const resource_storage& other) -> resource_storage& = delete;
86
87 template<typename... Args>
88 requires (std::is_constructible_v<value_type, Args...>)
89 auto emplace(Args&&... args) -> handle_type {
90 if (!_free_handles.empty()) {
91 const auto handle = _free_handles.back();
92 _free_handles.pop_back();
93
94 std::construct_at(_ptr(handle), std::forward<Args>(args)...);
95
96 const auto generation = ++_generations[handle];
97
98 return handle_type{handle, generation};
99 }
100
101 const auto handle = static_cast<std::uint32_t>(_storage.size());
102
103 _storage.emplace_back();
104 std::construct_at(_ptr(handle), std::forward<Args>(args)...);
105
106 _generations.push_back(0u);
107
108 return handle_type{handle, _generations[handle]};
109 }
110
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");
114
115 return *_ptr(handle.handle());
116 }
117
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");
121
122 return *_ptr(handle.handle());
123 }
124
125 auto remove(const handle_type& handle) -> void {
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");
128
129 std::destroy_at(_ptr(handle.handle()));
130 _free_handles.push_back(handle.handle());
131 }
132
133 auto clear() -> void {
134 auto free_list = std::unordered_set<std::uint32_t>{_free_handles.begin(), _free_handles.end()};
135
136 for (std::uint32_t i = 0; i < _storage.size(); ++i) {
137 if (free_list.contains(i)) {
138 continue;
139 }
140
141 std::destroy_at(_ptr(i));
142 }
143
144 _storage.clear();
145 _generations.clear();
146 _free_handles.clear();
147 }
148
149private:
150
151 auto _ptr(const size_type index) -> value_type* {
152 return std::launder(reinterpret_cast<value_type*>(_storage.data() + index));
153 }
154
155 auto _ptr(const size_type index) const -> const value_type* {
156 return std::launder(reinterpret_cast<const value_type*>(_storage.data() + index));
157 }
158
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;
162
163}; // class resource_storage
164
165} // namespace sbx::graphics
166
167template<typename Type>
168struct std::hash<sbx::graphics::resource_handle<Type>> {
169
170 auto operator()(const sbx::graphics::resource_handle<Type>& handle) const noexcept -> std::size_t {
171 auto hash = std::size_t{};
172
173 sbx::utility::hash_combine(hash, handle.handle(), handle.generation());
174
175 return hash;
176 }
177
178}; // struct std::hash
179
180#endif // LIBSBX_GRAPHICS_RESOURSE_STORAGE_HPP_
Definition: resource_storage.hpp:17
Definition: resource_storage.hpp:65
Definition: resource_storage.hpp:60