diff options
Diffstat (limited to 'src/handle-page.inl')
-rw-r--r-- | src/handle-page.inl | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/src/handle-page.inl b/src/handle-page.inl new file mode 100644 index 00000000..7c9d5a39 --- /dev/null +++ b/src/handle-page.inl @@ -0,0 +1,73 @@ +#pragma once +#include "handle-page.hpp" +#include "compat/assert.hpp" +#include "compat/pretty-function.hpp" + +namespace floormat::Handle { + +template<typename Obj, uint32_t PageSize> +Page<Obj, PageSize>::~Page() noexcept +{ + fm_assert(used_count == 0); +} + +template<typename Obj, uint32_t PageSize> +Page<Obj, PageSize>::Page(uint32_t start_index): + used_map{ValueInit, PageSize}, + start_index{start_index}, + first_free{start_index} +{ + fm_assert(size_t{start_index} + size_t{PageSize} <= 1<<31 && start_index + PageSize > start_index); + auto val = start_index; + for (auto i = 0u; i < PageSize; i++) + { + auto& o = storage.data()[i]; + o.handle = {val++, 0}; + o.next = val; + } +} + +template<typename Obj, uint32_t PageSize> +Item<Obj, PageSize>& Page<Obj, PageSize>::allocate() +{ + fm_assert(used_count < PageSize); + auto first_freeʹ = first_free - start_index; + fm_debug_assert(first_freeʹ < PageSize); + fm_debug_assert(!used_map[first_freeʹ]); + auto& item = storage[first_freeʹ]; + first_free = item.next; + used_count++; + used_map.set(first_freeʹ, true); + return item; +} + +template<typename Obj, uint32_t PageSize> +void Page<Obj, PageSize>::deallocate(Handle<Obj, PageSize> obj) +{ + auto index = obj.index - start_index; + fm_debug_assert(index < PageSize); + fm_assert(used_map[index]); + fm_debug_assert(used_count > 0); + fm_debug_assert(first_free != (uint32_t)-1); + auto& item = storage[index]; + auto ctr = ++item.handle.counter; + if (ctr == uint32_t{0}) [[unlikely]] + Debug{} << "counter" << FM_PRETTY_FUNCTION << "overflowed"; + item.next = first_free; + used_count--; + first_free = obj.index; +} + +template<typename Obj, uint32_t PageSize> +bool Page<Obj, PageSize>::is_empty() +{ + return used_count == 0; +} + +template<typename Obj, uint32_t PageSize> +bool Page<Obj, PageSize>::is_full() +{ + return used_count == PageSize; +} + +} // namespace floormat::Handle |