diff options
author | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-11-19 23:30:55 +0100 |
---|---|---|
committer | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-12-20 15:35:58 +0100 |
commit | f5ef1937eafb3d96b3683d92639a193694210c70 (patch) | |
tree | 0edcffc7447c42fe8467e2b788ee8f65f96b7fe2 /asl | |
parent | 3bddc19f5854857788330f11993336f645c414ab (diff) |
More work on asl::box
Diffstat (limited to 'asl')
-rw-r--r-- | asl/allocator.cpp | 10 | ||||
-rw-r--r-- | asl/allocator.hpp | 13 | ||||
-rw-r--r-- | asl/box.hpp | 83 | ||||
-rw-r--r-- | asl/meta.hpp | 3 | ||||
-rw-r--r-- | asl/tests/box_tests.cpp | 56 |
5 files changed, 159 insertions, 6 deletions
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<size_t>(new_layout.size),
+ static_cast<size_t>(new_layout.align));
+#elif ASL_OS_LINUX
if (new_layout.align <= old_layout.align)
{
void* new_ptr = ::realloc(old_ptr, static_cast<size_t>(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<typename T>
-concept allocator = requires(T& alloc, layout layout, void* ptr)
-{
- { alloc.alloc(layout) } -> same_as<void*>;
- { alloc.realloc(ptr, layout, layout) } -> same_as<void*>;
- alloc.dealloc(ptr, layout);
-};
+concept allocator = moveable<T> &&
+ requires(T& alloc, layout layout, void* ptr)
+ {
+ { alloc.alloc(layout) } -> same_as<void*>;
+ { alloc.realloc(ptr, layout, layout) } -> same_as<void*>;
+ 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<Allocator>
+ : 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<T>)
+ {
+ m_ptr->~T();
+ }
+ m_alloc.dealloc(m_ptr, layout::of<T>());
+ 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<is_object T, allocator Allocator = DefaultAllocator, typename... Args>
+constexpr box<T, Allocator> make_box_in(Allocator allocator, Args&&... args)
+ requires constructible_from<T, Args&&...>
+{
+ void* raw_ptr = allocator.alloc(layout::of<T>());
+ T* ptr = new (raw_ptr) T(ASL_FWD(args)...);
+ return box(ptr, ASL_MOVE(allocator));
+}
+
+template<is_object T, allocator Allocator = DefaultAllocator, typename... Args>
+constexpr box<T, Allocator> make_box(Args&&... args)
+ requires default_constructible<Allocator> && constructible_from<T, Args&&...>
+{
+ Allocator allocator{};
+ void* raw_ptr = allocator.alloc(layout::of<T>());
+ T* ptr = new (raw_ptr) T{ ASL_FWD(args)... };
+ return box<T>(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<typename T> concept trivially_destructible = __is_trivially_destructibl template<typename T> concept trivially_copyable = __is_trivially_copyable(T);
+template<typename T> concept copyable = copy_constructible<T> && copy_assignable<T>;
+template<typename T> concept moveable = move_constructible<T> && move_assignable<T>;
+
template<typename To, typename From>
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<int>) == sizeof(int*));
+static_assert(asl::default_constructible<asl::box<int>>);
+static_assert(!asl::copyable<asl::box<int>>);
+static_assert(asl::moveable<asl::box<int>>);
+static_assert(asl::default_constructible<asl::box<NonMoveConstructible>>);
+ASL_TEST(destructor)
+{
+ bool d = false;
+
+ {
+ asl::box<DestructorObserver> box2;
+
+ {
+ auto box = asl::make_box<DestructorObserver>(&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<int>(24);
+ ASL_TEST_EXPECT(*b == 24);
+
+ auto b2 = ASL_MOVE(b);
+ ASL_TEST_EXPECT(*b2 == 24);
+}
+
+ASL_TEST(ptr)
+{
+ auto b = asl::make_box<int>(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<Struct>(45);
+ ASL_TEST_EXPECT(b->a == 45);
+}
|