15 using id_t = std::uint32_t;
16 using generation_t = std::uint32_t;
19 static constexpr auto invalid_id = std::numeric_limits<id_t>::max();
22 static constexpr auto invalid_generation = std::numeric_limits<generation_t>::max();
26 [[nodiscard]]
static constexpr handle invalid() noexcept {
27 return handle{ invalid_id, invalid_generation };
31 constexpr handle() =
default;
36 explicit constexpr handle(id_t
id, generation_t generation = 0) noexcept : _id(
id), _generation(generation) {
41 [[nodiscard]]
constexpr auto valid() const noexcept ->
bool {
42 return *
this != handle::invalid();
47 [[nodiscard]]
constexpr auto id() const noexcept {
53 [[nodiscard]]
constexpr auto generation() const noexcept {
60 [[nodiscard]]
constexpr auto operator<=>(
const handle& rhs)
const =
default;
63 id_t _id{ invalid_id };
64 generation_t _generation{ invalid_generation };
74 [[nodiscard]]
constexpr auto create() -> H {
75 if (!_free_ids.empty()) {
76 auto id = _free_ids.back();
78 _free_cursor.store(_free_ids.size(), std::memory_order::relaxed);
79 return H{ id, _generations[id] };
81 auto handle = H{ _next_id.fetch_add(1, std::memory_order::relaxed) };
82 _generations.emplace_back();
89 [[nodiscard]]
constexpr auto alive(H handle)
const noexcept ->
bool {
90 if (handle.id() < _generations.size()) {
91 return _generations[handle.id()] == handle.generation();
98 constexpr void recycle(H handle) {
102 _generations[handle.id()]++;
103 _free_ids.push_back(handle.id());
104 _free_cursor.fetch_add(1, std::memory_order::relaxed);
110 constexpr auto reserve() -> H {
111 auto n = _free_cursor.fetch_sub(1, std::memory_order::relaxed);
113 auto id = _free_ids[n - 1];
114 return H{ id, _generations[id] };
116 auto handle = H{ _next_id.fetch_add(1, std::memory_order::relaxed) };
121 constexpr void flush() {
122 auto free_cursor = _free_cursor.load(std::memory_order::relaxed);
124 while (free_cursor < 0) {
125 _generations.emplace_back();
129 while (_free_ids.size() > free_cursor) {
130 _free_ids.pop_back();
133 _free_cursor.store(free_cursor, std::memory_order::relaxed);
137 std::atomic<typename H::id_t> _next_id{};
138 std::atomic<std::int64_t> _free_cursor{};
139 std::vector<typename H::generation_t> _generations;
140 std::vector<typename H::id_t> _free_ids;
Definition component.hpp:17