From f5ef1937eafb3d96b3683d92639a193694210c70 Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Tue, 19 Nov 2024 23:30:55 +0100 Subject: More work on asl::box --- asl/allocator.cpp | 10 ++++++ asl/allocator.hpp | 13 ++++---- asl/box.hpp | 83 +++++++++++++++++++++++++++++++++++++++++++++++++ asl/meta.hpp | 3 ++ asl/tests/box_tests.cpp | 56 +++++++++++++++++++++++++++++++++ 5 files changed, 159 insertions(+), 6 deletions(-) (limited to 'asl') diff --git a/asl/allocator.cpp b/asl/allocator.cpp index f50b42b..8fbca4e 100644 --- a/asl/allocator.cpp +++ b/asl/allocator.cpp @@ -26,6 +26,11 @@ void* asl::GlobalHeap::alloc(const layout& layout) void* asl::GlobalHeap::realloc(void* old_ptr, const layout& old_layout, const layout& new_layout) { +#if ASL_OS_WINDOWS + return ::_aligned_realloc(old_ptr, + static_cast(new_layout.size), + static_cast(new_layout.align)); +#elif ASL_OS_LINUX if (new_layout.align <= old_layout.align) { void* new_ptr = ::realloc(old_ptr, static_cast(new_layout.size)); @@ -36,9 +41,14 @@ void* asl::GlobalHeap::realloc(void* old_ptr, const layout& old_layout, const la void* new_ptr = alloc(new_layout); asl::memcpy(new_ptr, old_ptr, asl::min(old_layout.size, new_layout.size)); return new_ptr; +#endif } void asl::GlobalHeap::dealloc(void* ptr, const layout&) { +#if ASL_OS_WINDOWS + ::_aligned_free(ptr); +#elif ASL_OS_LINUX ::free(ptr); +#endif } diff --git a/asl/allocator.hpp b/asl/allocator.hpp index b6c1a9a..eb03e0f 100644 --- a/asl/allocator.hpp +++ b/asl/allocator.hpp @@ -7,12 +7,13 @@ namespace asl { template -concept allocator = requires(T& alloc, layout layout, void* ptr) -{ - { alloc.alloc(layout) } -> same_as; - { alloc.realloc(ptr, layout, layout) } -> same_as; - alloc.dealloc(ptr, layout); -}; +concept allocator = moveable && + requires(T& alloc, layout layout, void* ptr) + { + { alloc.alloc(layout) } -> same_as; + { alloc.realloc(ptr, layout, layout) } -> same_as; + alloc.dealloc(ptr, layout); + }; class GlobalHeap { diff --git a/asl/box.hpp b/asl/box.hpp index 0cab66b..d8ccd36 100644 --- a/asl/box.hpp +++ b/asl/box.hpp @@ -1,7 +1,10 @@ #pragma once #include "asl/allocator.hpp" +#include "asl/assert.hpp" #include "asl/annotations.hpp" +#include "asl/memory.hpp" +#include "asl/utility.hpp" namespace asl { @@ -13,7 +16,87 @@ class box ASL_NO_UNIQUE_ADDRESS Allocator m_alloc; public: + explicit constexpr box(T* ptr = nullptr) + requires default_constructible + : m_ptr{ptr} + {} + + constexpr box(T* ptr, Allocator alloc) + : m_ptr{ptr} + , m_alloc{ASL_MOVE(alloc)} + {} + + constexpr box(box&& other) + : m_ptr{exchange(other.m_ptr, nullptr)} + , m_alloc{ASL_MOVE(other.m_alloc)} + {} + + constexpr box& operator=(box&& other) + { + if (this == &other) { return *this; } + + if (m_ptr != nullptr) { reset(); } + + m_ptr = exchange(other.m_ptr, nullptr); + m_alloc = ASL_MOVE(other.m_alloc); + + return *this; + } + + box(const box&) = delete; + box& operator=(const box&) = delete; + + constexpr ~box() + { + reset(); + } + + constexpr void reset() + { + if (m_ptr != nullptr) + { + if constexpr (!trivially_destructible) + { + m_ptr->~T(); + } + m_alloc.dealloc(m_ptr, layout::of()); + m_ptr = nullptr; + } + } + + constexpr T* get() const { return m_ptr; } + + constexpr T& operator*() const + { + ASL_ASSERT(m_ptr != nullptr); + return *m_ptr; + } + + constexpr T* operator->() const + { + ASL_ASSERT(m_ptr != nullptr); + return m_ptr; + } }; +template +constexpr box make_box_in(Allocator allocator, Args&&... args) + requires constructible_from +{ + void* raw_ptr = allocator.alloc(layout::of()); + T* ptr = new (raw_ptr) T(ASL_FWD(args)...); + return box(ptr, ASL_MOVE(allocator)); +} + +template +constexpr box make_box(Args&&... args) + requires default_constructible && constructible_from +{ + Allocator allocator{}; + void* raw_ptr = allocator.alloc(layout::of()); + T* ptr = new (raw_ptr) T{ ASL_FWD(args)... }; + return box(ptr, ASL_MOVE(allocator)); +} + } // namespace asl diff --git a/asl/meta.hpp b/asl/meta.hpp index 552bf0c..f0397a1 100644 --- a/asl/meta.hpp +++ b/asl/meta.hpp @@ -69,6 +69,9 @@ template concept trivially_destructible = __is_trivially_destructibl template concept trivially_copyable = __is_trivially_copyable(T); +template concept copyable = copy_constructible && copy_assignable; +template concept moveable = move_constructible && move_assignable; + template concept convertible_from = __is_convertible(From, To); diff --git a/asl/tests/box_tests.cpp b/asl/tests/box_tests.cpp index 6c4d543..f1a35f3 100644 --- a/asl/tests/box_tests.cpp +++ b/asl/tests/box_tests.cpp @@ -1,6 +1,62 @@ #include "asl/box.hpp" #include "asl/testing/testing.hpp" +#include "asl/tests/test_types.hpp" static_assert(sizeof(asl::box) == sizeof(int*)); +static_assert(asl::default_constructible>); +static_assert(!asl::copyable>); +static_assert(asl::moveable>); +static_assert(asl::default_constructible>); +ASL_TEST(destructor) +{ + bool d = false; + + { + asl::box box2; + + { + auto box = asl::make_box(&d); + ASL_TEST_ASSERT(!d); + + + auto box3 = ASL_MOVE(box); + ASL_TEST_ASSERT(!d); + + box2 = ASL_MOVE(box3); + ASL_TEST_ASSERT(!d); + } + + ASL_TEST_ASSERT(!d); + } + + ASL_TEST_ASSERT(d); +} + +ASL_TEST(value) +{ + auto b = asl::make_box(24); + ASL_TEST_EXPECT(*b == 24); + + auto b2 = ASL_MOVE(b); + ASL_TEST_EXPECT(*b2 == 24); +} + +ASL_TEST(ptr) +{ + auto b = asl::make_box(24); + auto* ptr1 = b.get(); + + auto b2 = ASL_MOVE(b); + auto* ptr2 = b2.get(); + ASL_TEST_EXPECT(ptr1 == ptr2); +} + +struct Struct { int a; }; + +ASL_TEST(arrow) +{ + auto b = asl::make_box(45); + ASL_TEST_EXPECT(b->a == 45); +} -- cgit