diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2024-07-14 09:43:59 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2024-07-14 13:04:43 +0200 |
commit | 3eb7e8d5a8b75a645d9994152451ce213e164887 (patch) | |
tree | 8fcc0585d46796ef593195f2f93f3bd34a7722bb | |
parent | b99da22eec9ff299141f51f94a5b6b88640d0b60 (diff) |
zz
-rw-r--r-- | src/handle-fwd.hpp | 32 | ||||
-rw-r--r-- | src/handle-page.hpp | 53 | ||||
-rw-r--r-- | src/handle-page.inl | 131 | ||||
-rw-r--r-- | src/handle-pool.hpp | 34 | ||||
-rw-r--r-- | src/handle-pool.inl | 47 | ||||
-rw-r--r-- | src/handle.cpp | 12 | ||||
-rw-r--r-- | src/handle.hpp | 25 | ||||
-rw-r--r-- | src/handle.inl | 40 | ||||
-rw-r--r-- | test/handle.cpp | 74 |
9 files changed, 0 insertions, 448 deletions
diff --git a/src/handle-fwd.hpp b/src/handle-fwd.hpp deleted file mode 100644 index 3e010f6d..00000000 --- a/src/handle-fwd.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -namespace floormat::impl_handle { - -template<typename OBJ, uint32_t PAGE_SIZE> struct Handle; -template<typename Obj, uint32_t PageSize> struct Item; -template<typename Obj, uint32_t PageSize> class Page; -template<typename Obj, uint32_t PageSize> class Pool; - -template<typename OBJ, uint32_t PAGE_SIZE> -struct Handle final -{ - uint32_t index = (uint32_t)-1; - uint32_t counter = 0; - - const OBJ& get() const; - OBJ& get(); - bool operator==(const Handle& other) const noexcept; - explicit operator bool() const noexcept; - -private: - static Item<OBJ, PAGE_SIZE>& get_from_pool(uint32_t index, uint32_t counter); -}; - -} // namespace floormat::impl_handle - -namespace floormat { - -template<typename Obj, uint32_t PageSize> -using handle = struct impl_handle::Handle<Obj, PageSize>; - -} // namespace floormat diff --git a/src/handle-page.hpp b/src/handle-page.hpp deleted file mode 100644 index 7afad5f8..00000000 --- a/src/handle-page.hpp +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once -#include "handle-fwd.hpp" -#include "compat/defs.hpp" -#include <array> -#include <cr/BitArray.h> - -namespace floormat::impl_handle { - -template<typename Obj, uint32_t PageSize> -struct Item -{ - fm_DECLARE_DELETED_COPY_MOVE_ASSIGNMENTS(Item); - Item(); - ~Item() noexcept; - - union { char empty = {}; Obj object; }; - Handle<Obj, PageSize> handle; - uint32_t next; -}; - -template<typename Obj, uint32_t PageSize> -class Page -{ - friend struct Handle<Obj, PageSize>; - - std::array<Item<Obj, PageSize>, PageSize> storage; - BitArray used_map; // todo replace with a rewrite of std::bitset - uint32_t start_index; - uint32_t used_count; - uint32_t first_free; - bool locked; - - static void do_deallocate(Item<Obj, PageSize>& item); - -public: - fm_DECLARE_DELETED_COPY_MOVE_ASSIGNMENTS(Page); - - explicit Page(uint32_t start_index); - ~Page() noexcept; - - 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(); - uint32_t use_count() const; -}; - -} // namespace floormat::impl_handle diff --git a/src/handle-page.inl b/src/handle-page.inl deleted file mode 100644 index 5eae88de..00000000 --- a/src/handle-page.inl +++ /dev/null @@ -1,131 +0,0 @@ -#pragma once -#include "handle-page.hpp" -#include "compat/assert.hpp" -#include "compat/pretty-function.hpp" - -namespace floormat::impl_handle { - -template<typename Obj, uint32_t PageSize> -Item<Obj, PageSize>::Item() = default; - -template<typename Obj, uint32_t PageSize> -Item<Obj, PageSize>::~Item() noexcept -{} - -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); -} - -template<typename Obj, uint32_t PageSize> -Page<Obj, PageSize>::Page(uint32_t start_index): - used_map{ValueInit, PageSize}, - start_index{start_index}, - used_count{0}, - first_free{start_index}, - locked{false} -{ - fm_assert(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> -template<typename... Xs> -requires requires (Xs&&... xs) { - Obj{forward<Xs>(xs)...}; -} -Item<Obj, PageSize>& Page<Obj, PageSize>::allocate(Xs&&... xs) -{ - fm_assert(!locked); - locked = true; - 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); - new (&item.object) Obj{ forward<Xs>(xs)... }; - locked = false; - return item; -} - -template<typename Obj, uint32_t PageSize> -void Page<Obj, PageSize>::deallocate(Handle<Obj, PageSize> obj) -{ - fm_assert(!locked); - locked = true; - 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)-1) [[unlikely]] - fm_debug("counter overflowed: %s", FM_PRETTY_FUNCTION); - fm_assert(obj.counter == ctr); - item.next = first_free; - first_free = obj.index; - used_count--; - used_map.set(index, false); - do_deallocate(item); - locked = false; -} - -template<typename Obj, uint32_t PageSize> -void Page<Obj, PageSize>::deallocate_all() -{ - fm_assert(!locked); - locked = true; - 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]; - bool used = used_map[i]; - uint32_t new_ctr = used ? 1 : 0; - o.handle = {val++, o.handle.counter + new_ctr}; - o.next = val; - } - first_free = start_index; - used_count = 0; - used_map = BitArray{ValueInit, PageSize}; - locked = false; -} - -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; -} - -template<typename Obj, uint32_t PageSize> -uint32_t Page<Obj, PageSize>::use_count() const -{ - return used_count; -} - -} // namespace floormat::impl_handle diff --git a/src/handle-pool.hpp b/src/handle-pool.hpp deleted file mode 100644 index 2721f094..00000000 --- a/src/handle-pool.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include "compat/defs.hpp" -#include <cr/Array.h> -#include <cr/Pointer.h> - -namespace floormat::impl_handle { - -template<typename Obj, uint32_t PageSize> -class Pool -{ - friend class impl_handle<Obj, PageSize>; - - static Pointer<Pool<Obj, PageSize>> make_pool(); - static Page<Obj, PageSize>& find_page(); - - Array<Pointer<Page<Obj, PageSize>>> pages; - size_t next_page_offset = 0; - - static Pointer<Pool<Obj, PageSize>> pool = make_pool(); - -public: - fm_DECLARE_DELETED_COPY_MOVE_ASSIGNMENTS(Pool); - - explicit Pool(); - ~Pool() noexcept; - - template<typename... Xs> - requires requires (Xs&&... xs) { - Obj{forward<Xs>(xs)...}; - } - static impl_handle<Obj, PageSize> make_object(Xs&&... xs); -}; - -} // namespace floormat::impl_handle diff --git a/src/handle-pool.inl b/src/handle-pool.inl deleted file mode 100644 index 1420bd7b..00000000 --- a/src/handle-pool.inl +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once -#include "handle-pool.hpp" -#include "handle-page.hpp" -#include "compat/move.hpp" -#include <cr/GrowableArray.h> - -namespace floormat::impl_handle { - -template<typename Obj, uint32_t PageSize> -template<typename... Xs> -requires requires (Xs&&... xs) { - Obj{forward<Xs>(xs)...}; -} -Handle<Obj, PageSize> Pool<Obj, PageSize>::make_object(Xs&&... xs) -{ - auto ret = std::shared_ptr<T>(new Obj{forward<Xs>(xs)...}); - do_make_object(std::static_pointer_cast<object>(ret)); - return ret; -} - -template<typename Obj, uint32_t PageSize> -Pointer<Pool<Obj, PageSize>> -Pool<Obj, PageSize>::make_pool() -{ - auto pool = Pointer<Pool<Obj, PageSize>>{InPlace}; - arrayReserve(pool->pages, 16); - return pool; -} - -template<typename Obj, uint32_t PageSize> -Page<Obj, PageSize>& -Pool<Obj, PageSize>::find_page() -{ - auto& P = *pool; - auto sz = P.pages.size(); - for (auto i = 0uz; i < sz; i++) - { - auto& p = *P.pages.data()[i]; - if (!p.is_full()) - return p; - } - arrayAppend(P.pages, InPlace, InPlace, P.next_page_offset); - P.next_page_offset += PageSize; - return P.pages.back(); -} - -} // namespace floormat::impl_handle diff --git a/src/handle.cpp b/src/handle.cpp deleted file mode 100644 index ff9ed4db..00000000 --- a/src/handle.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "handle.inl" - -namespace floormat::impl_handle { - -} // namespace floormat::impl_handle - - -namespace floormat { - - - -} // namespace floormat diff --git a/src/handle.hpp b/src/handle.hpp deleted file mode 100644 index 89c1c480..00000000 --- a/src/handle.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -#include "handle-fwd.hpp" -#include "compat/assert.hpp" - -namespace floormat::impl_handle { - -template<typename Obj, uint32_t PageSize> -bool Handle<Obj, PageSize>::operator==(const Handle& other) const noexcept -{ - bool ret = index == other.index; - fm_debug_assert(!ret || counter == other.counter); - return ret; -} - -template<typename Obj, uint32_t PageSize> -Handle<Obj, PageSize>::operator bool() const noexcept -{ - return index != (uint32_t)-1; -} - -} // namespace floormat::impl_handle - -namespace floormat { - -} // namespace floormat diff --git a/src/handle.inl b/src/handle.inl deleted file mode 100644 index f19ec216..00000000 --- a/src/handle.inl +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include "handle.hpp" -//#include "handle-pool.inl" -#include "compat/assert.hpp" - -namespace floormat::impl_handle { - -template<typename Obj, uint32_t PageSize> -const Obj& Handle<Obj, PageSize>::get() const -{ - return get_from_pool(index, counter).object; -} - -template<typename Obj, uint32_t PageSize> -Obj& Handle<Obj, PageSize>::get() -{ - return get_from_pool(index, counter).object; -} - -template<typename Obj, uint32_t PageSize> -Item<Obj, PageSize>& Handle<Obj, PageSize>::get_from_pool(uint32_t index, uint32_t counter) -{ - auto page_idx = index / PageSize; - auto obj_idx = index % PageSize; - fm_assert(Pool<Obj, PageSize>::pages.size() < page_idx); - auto& page = Pool<Obj, PageSize>::pages.data()[page_idx]; - auto& item = page->storage[obj_idx]; - fm_debug_assert(page.used_map[obj_idx]); - fm_assert(item.handle.counter == counter); - fm_debug_assert(item.handle == index + page.start_index); - return item.object; -} - -} // namespace floormat::impl_handle - -namespace floormat { - - - -} // namespace floormat diff --git a/test/handle.cpp b/test/handle.cpp deleted file mode 100644 index 2c29f52c..00000000 --- a/test/handle.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "app.hpp" -//#include "src/handle.inl" -#include "src/handle.hpp" -#include "src/handle-page.inl" -//#include "src/handle-pool.inl" - -namespace floormat { -namespace { - -constexpr uint32_t start_index = 1024, page_size = 256; - -struct Foo -{ - int value = 0; - ~Foo() { value = 0; } -}; - -using Page = impl_handle::Page<Foo, page_size>; -using Handle = impl_handle::Handle<Foo, page_size>; - -} // namespace -} // namespace floormat - -namespace floormat::impl_handle { - -template struct Handle<Foo, page_size>; -template struct Item<Foo, page_size>; // NOLINT(*-pro-type-member-init) -template class Page<Foo, page_size>; -//template class Pool<Foo, page_size>; - -} // namespace floormat::impl_handle - - -namespace floormat::Test { - -namespace { - -void test_page1() -{ - Page page{start_index}; - auto& item0 = page.allocate(1); - fm_assert(page.use_count() == 1); - auto handle0 = item0.handle; - fm_assert(item0.handle == Handle{start_index, 0}); - fm_assert(item0.object.value == 1); - page.deallocate(item0.handle); - fm_assert(page.use_count() == 0); - - auto& item1 = page.allocate(2); - fm_assert(page.use_count() == 1); - auto& item2 = page.allocate(3); - fm_assert(page.use_count() == 2); - 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); - page.deallocate(item2.handle); - page.deallocate(item1.handle); - fm_assert(item0.object.value == 0); - fm_assert(item1.object.value == 0); - fm_assert(item2.object.value == 0); - fm_assert(page.use_count() == 0); -} -} // namespace - - -void test_handle() -{ - test_page1(); -} - -} // namespace floormat::Test |