diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/handle-page.hpp | 11 | ||||
-rw-r--r-- | src/handle-page.inl | 34 |
2 files changed, 41 insertions, 4 deletions
diff --git a/src/handle-page.hpp b/src/handle-page.hpp index c0397db7..057a512e 100644 --- a/src/handle-page.hpp +++ b/src/handle-page.hpp @@ -9,7 +9,7 @@ namespace floormat::impl_handle { template<typename Obj, uint32_t PageSize> struct Item { - union { Obj object; }; + union { char empty = {}; Obj object; }; Handle<Obj, PageSize> handle; uint32_t next; }; @@ -25,14 +25,21 @@ class Page uint32_t used_count = 0; uint32_t first_free = (uint32_t)-1; + static void do_deallocate(Item<Obj, PageSize>& item); + public: fm_DECLARE_DELETED_COPY_MOVE_ASSIGNMENTS(Page); explicit Page(uint32_t start_index); ~Page() noexcept; - [[nodiscard]] Item<Obj, PageSize>& allocate(); + template<typename... Xs> + requires requires (Xs&&... xs) { + Obj{forward<Xs>(xs)...}; + } + [[nodiscard]] Item<Obj, PageSize>& allocate(Xs&&... xs); void deallocate(Handle<Obj, PageSize> obj); + void deallocate_all(); bool is_empty(); bool is_full(); }; diff --git a/src/handle-page.inl b/src/handle-page.inl index fbd28043..8a8bd489 100644 --- a/src/handle-page.inl +++ b/src/handle-page.inl @@ -6,6 +6,12 @@ namespace floormat::impl_handle { template<typename Obj, uint32_t PageSize> +void Page<Obj, PageSize>::do_deallocate(Item<Obj, PageSize>& item) +{ + item.object.~Obj(); +} + +template<typename Obj, uint32_t PageSize> Page<Obj, PageSize>::~Page() noexcept { fm_assert(used_count == 0); @@ -28,7 +34,11 @@ Page<Obj, PageSize>::Page(uint32_t start_index): } template<typename Obj, uint32_t PageSize> -Item<Obj, PageSize>& Page<Obj, PageSize>::allocate() +template<typename... Xs> +requires requires (Xs&&... xs) { + Obj{forward<Xs>(xs)...}; +} +Item<Obj, PageSize>& Page<Obj, PageSize>::allocate(Xs&&... xs) { fm_assert(used_count < PageSize); auto first_freeʹ = first_free - start_index; @@ -38,6 +48,7 @@ Item<Obj, PageSize>& Page<Obj, PageSize>::allocate() first_free = item.next; used_count++; used_map.set(first_freeʹ, true); + new (&item.object) Obj{ forward<Xs>(xs)... }; return item; } @@ -55,9 +66,28 @@ void Page<Obj, PageSize>::deallocate(Handle<Obj, PageSize> obj) Debug{} << "counter" << FM_PRETTY_FUNCTION << "overflowed"; fm_assert(obj.counter == ctr); item.next = first_free; + first_free = obj.index; used_count--; used_map.set(index, false); - first_free = obj.index; + do_deallocate(item); +} + +template<typename Obj, uint32_t PageSize> +void Page<Obj, PageSize>::deallocate_all() +{ + for (auto i = 0u; i < PageSize; i++) + if (used_map[i]) + do_deallocate(storage[i]); + auto val = start_index; + for (auto i = 0u; i < PageSize; i++) + { + auto& o = storage.data()[i]; + o.handle = {val++, 0}; + o.next = val; + } + first_free = start_index; + used_count = 0; + used_map = BitArray{ValueInit, PageSize}; } template<typename Obj, uint32_t PageSize> |