diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2024-07-12 23:49:45 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2024-07-14 13:04:41 +0200 |
commit | 7d309c5cdf61ec186046fc7d83e641853c8706ac (patch) | |
tree | d8eeadfced1077e1ea2834b6f5bb9b642eea7718 | |
parent | 2a597bdcfcb6fd685be121d7f52693832c122589 (diff) |
w
-rw-r--r-- | src/handle-page.hpp | 11 | ||||
-rw-r--r-- | src/handle-page.inl | 34 | ||||
-rw-r--r-- | test/handle.cpp | 13 |
3 files changed, 49 insertions, 9 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> diff --git a/test/handle.cpp b/test/handle.cpp index cbec8cac..2b52b04e 100644 --- a/test/handle.cpp +++ b/test/handle.cpp @@ -8,7 +8,7 @@ namespace floormat { namespace { constexpr uint32_t start_index = 1024, page_size = 128; -struct Foo { int value; }; +struct Foo { int value = 0; }; using Page = impl_handle::Page<Foo, page_size>; using Handle = impl_handle::Handle<Foo, page_size>; @@ -32,14 +32,17 @@ namespace { void test_page1() { Page page{start_index}; - auto& item0 = page.allocate(); + auto& item0 = page.allocate(1); auto handle0 = item0.handle; fm_assert(item0.handle == Handle{start_index}); + fm_assert(item0.object.value == 1); page.deallocate(item0.handle); - auto& item1 = page.allocate(); - auto& item2 = page.allocate(); - fm_assert(item1.handle.index == start_index || item2.handle.index == start_index); + auto& item1 = page.allocate(2); + auto& item2 = page.allocate(3); + fm_assert(item1.object.value == 2); + fm_assert(item2.object.value == 3); + fm_assert(item1.handle.index == item0.handle.index || item2.handle.index == item0.handle.index); fm_assert(item1.handle.index != item2.handle.index); fm_assert(item1.handle.counter != item2.handle.counter); fm_assert(int{item1.handle.counter != handle0.counter} + int{item2.handle.counter != handle0.counter} == 1); |