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{0x00FFFFFF};
24
25 constexpr resource_handle()
26 : _handle{invalid},
27 _generation{0} { }
28
29 constexpr resource_handle(const std::uint32_t handle, const std::uint8_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::uint8_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 return std::memcmp(this, &other, sizeof(std::uint32_t)) == 0;
45 }
46
47 constexpr auto is_valid() const noexcept -> bool {
48 return _handle != invalid;
49 }
50
51 constexpr operator bool() const noexcept {
52 return is_valid();
53 }
54
55private:
56
57 std::uint32_t _handle : 24;
58 std::uint32_t _generation : 8;
59
60}; // class resource_handle
61
63 std::filesystem::path path;
64}; // struct resource_metadata
65
66template<typename Type>
68
69public:
70
71 using value_type = Type;
72 using size_type = std::size_t;
74
76 _storage.reserve(32u);
77 _generations.reserve(32u);
78 _free_handles.reserve(32u);
79 }
80
81 resource_storage(const resource_storage& other) = delete;
82
84 clear();
85 }
86
87 auto operator=(const resource_storage& other) -> resource_storage& = delete;
88
89 template<typename... Args>
90 requires (std::is_constructible_v<value_type, Args...>)
91 auto emplace(Args&&... args) -> handle_type {
92 if (!_free_handles.empty()) {
93 const auto handle = _free_handles.back();
94 _free_handles.pop_back();
95
96 std::construct_at(_ptr(handle), std::forward<Args>(args)...);
97
98 const auto generation = ++_generations[handle];
99
100 return handle_type{handle, generation};
101 }
102
103 const auto handle = static_cast<std::uint32_t>(_storage.size());
104
105 _storage.emplace_back();
106 std::construct_at(_ptr(handle), std::forward<Args>(args)...);
107
108 _generations.push_back(0u);
109
110 return handle_type{handle, _generations[handle]};
111 }
112
113 auto get(const handle_type& handle) -> value_type& {
114 utility::assert_that(handle.handle() < _storage.size(), "Handle is out of bounds");
115 utility::assert_that(handle.generation() == _generations[handle.handle()], "Handle generation does not match");
116
117 return *_ptr(handle.handle());
118 }
119
120 auto get(const handle_type& handle) const -> const value_type& {
121 utility::assert_that(handle.handle() < _storage.size(), "Handle is out of bounds");
122 utility::assert_that(handle.generation() == _generations[handle.handle()], "Handle generation does not match");
123
124 return *_ptr(handle.handle());
125 }
126
127 auto remove(const handle_type& handle) -> void {
128 utility::assert_that(handle.handle() < _storage.size(), "Handle is out of bounds");
129 utility::assert_that(handle.generation() == _generations[handle.handle()], "Handle generation does not match");
130
131 std::destroy_at(_ptr(handle.handle()));
132 _free_handles.push_back(handle.handle());
133 }
134
135 auto clear() -> void {
136 auto free_list = std::unordered_set<std::uint32_t>{_free_handles.begin(), _free_handles.end()};
137
138 for (std::uint32_t i = 0; i < _storage.size(); ++i) {
139 if (free_list.contains(i)) {
140 continue;
141 }
142
143 std::destroy_at(_ptr(i));
144 }
145
146 _storage.clear();
147 _generations.clear();
148 _free_handles.clear();
149 }
150
151private:
152
153 auto _ptr(const size_type index) -> value_type* {
154 return std::launder(reinterpret_cast<value_type*>(_storage.data() + index));
155 }
156
157 auto _ptr(const size_type index) const -> const value_type* {
158 return std::launder(reinterpret_cast<const value_type*>(_storage.data() + index));
159 }
160
161 std::vector<memory::storage_for_t<value_type>> _storage;
162 std::vector<std::uint8_t> _generations;
163 std::vector<std::uint32_t> _free_handles;
164
165}; // class resource_storage
166
167} // namespace sbx::graphics
168
169template<typename Type>
170struct std::hash<sbx::graphics::resource_handle<Type>> {
171
172 auto operator()(const sbx::graphics::resource_handle<Type>& handle) const noexcept -> std::size_t {
173 auto hash = std::size_t{};
174
175 sbx::utility::hash_combine(hash, handle.handle(), handle.generation());
176
177 return hash;
178 }
179
180}; // struct std::hash
181
182#endif // LIBSBX_GRAPHICS_RESOURSE_STORAGE_HPP_
Definition: resource_storage.hpp:17
Definition: resource_storage.hpp:67
Definition: resource_storage.hpp:62