summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Le Rouzic <steven.lerouzic@gmail.com>2025-01-01 19:18:19 +0100
committerSteven Le Rouzic <steven.lerouzic@gmail.com>2025-01-01 19:18:19 +0100
commit22131693e1892c5477c998ab63bf476d152b17cb (patch)
tree8cd7fbf85aa7a24db3da3d2ac1a86ec6d4c4f0f9
parentb2eddfabffeb78fc5b49f9c17d70175d2dfed2e0 (diff)
Implement move constructor for buffer
-rw-r--r--asl/box.hpp2
-rw-r--r--asl/buffer.hpp21
-rw-r--r--asl/maybe_uninit.hpp2
-rw-r--r--asl/memory.hpp8
-rw-r--r--asl/option.hpp2
-rw-r--r--asl/testing/testing.cpp8
-rw-r--r--asl/tests/buffer_tests.cpp55
-rw-r--r--asl/tests/test_types.hpp1
8 files changed, 82 insertions, 17 deletions
diff --git a/asl/box.hpp b/asl/box.hpp
index 198fada..491338f 100644
--- a/asl/box.hpp
+++ b/asl/box.hpp
@@ -58,7 +58,7 @@ public:
{
if (m_ptr != nullptr)
{
- destruct(m_ptr);
+ destroy(m_ptr);
m_alloc.dealloc(m_ptr, layout::of<T>());
m_ptr = nullptr;
}
diff --git a/asl/buffer.hpp b/asl/buffer.hpp
index 9020a99..84284bc 100644
--- a/asl/buffer.hpp
+++ b/asl/buffer.hpp
@@ -100,9 +100,8 @@ private:
constexpr void set_size(isize_t new_size)
{
- ASL_ASSERT(new_size >= 0);
- ASL_ASSERT_RELEASE(new_size <= capacity());
- if (kInlineCapacity == 0 || is_on_heap())
+ ASL_ASSERT(new_size >= 0 && new_size <= capacity());
+ if (is_on_heap())
{
store_size_encoded(encode_size_heap(new_size));
}
@@ -124,22 +123,23 @@ public:
{
if (other.is_on_heap())
{
- // @Todo Test this
- destroy();
m_data = other.m_data;
m_capacity = other.m_capacity;
- set_size(other.size());
+ store_size_encoded(other.load_size_encoded());
}
else if (trivially_move_constructible<T>)
{
- // @Todo Test this
- destroy();
asl::memcpy(this, &other, kInlineRegionSize);
}
else
{
- // @Todo
+ isize_t n = other.size();
+ ASL_ASSERT(n <= kInlineCapacity);
+ relocate_uninit_n(data(), other.data(), n);
+ set_size_inline(n);
}
+
+ other.set_size_inline(0);
}
~buffer()
@@ -171,7 +171,7 @@ public:
isize_t current_size = size();
if (current_size == 0) { return; }
- destruct_n(data(), current_size);
+ destroy_n(data(), current_size);
set_size(0);
}
@@ -185,6 +185,7 @@ public:
auto current_layout = layout::array<T>(m_capacity);
m_allocator.dealloc(m_data, current_layout);
}
+ set_size_inline(0);
}
}
diff --git a/asl/maybe_uninit.hpp b/asl/maybe_uninit.hpp
index cedd96f..e59cfe0 100644
--- a/asl/maybe_uninit.hpp
+++ b/asl/maybe_uninit.hpp
@@ -53,7 +53,7 @@ public:
// @Safety Must be called only when in initialized state.
constexpr void uninit_unsafe() &
{
- destruct(init_ptr_unsafe());
+ destroy(init_ptr_unsafe());
}
};
diff --git a/asl/memory.hpp b/asl/memory.hpp
index 0441c8c..cfc7057 100644
--- a/asl/memory.hpp
+++ b/asl/memory.hpp
@@ -36,7 +36,7 @@ constexpr T* construct_at(void* ptr, Args&&... args)
}
template<typename T>
-constexpr void destruct(T* data)
+constexpr void destroy(T* data)
{
if constexpr (!trivially_destructible<T>)
{
@@ -45,13 +45,13 @@ constexpr void destruct(T* data)
}
template<typename T>
-constexpr void destruct_n(T* data, isize_t n)
+constexpr void destroy_n(T* data, isize_t n)
{
if constexpr (!trivially_destructible<T>)
{
for (isize_t i = 0; i < n; ++i)
{
- destruct(data + i);
+ destroy(data + i);
}
}
}
@@ -71,7 +71,7 @@ constexpr void relocate_uninit_n(T* to, T* from, isize_t n)
// NOLINTNEXTLINE(*-pointer-arithmetic)
construct_at<T>(to + i, ASL_MOVE(from[i]));
}
- destruct_n(from, n);
+ destroy_n(from, n);
}
}
diff --git a/asl/option.hpp b/asl/option.hpp
index 8deed69..b87a5ab 100644
--- a/asl/option.hpp
+++ b/asl/option.hpp
@@ -383,7 +383,7 @@ public:
}
else
{
- destruct(&m_payload);
+ destroy(&m_payload);
construct_at<T>(&m_payload, niche{});
}
}
diff --git a/asl/testing/testing.cpp b/asl/testing/testing.cpp
index 405df34..aff6a74 100644
--- a/asl/testing/testing.cpp
+++ b/asl/testing/testing.cpp
@@ -38,6 +38,8 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
{
int fail = 0;
int pass = 0;
+
+ asl::testing::Test* failed_head = nullptr;
for (auto* it = g_head; it != nullptr; it = it->m_next)
{
@@ -55,6 +57,8 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
{
asl::eprint(RED("[ FAILED ]") " {}\n", it->m_case_name);
fail += 1;
+
+ it->m_next = asl::exchange(failed_head, it);
}
}
@@ -67,6 +71,10 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
else
{
asl::eprint(RED("[ FAILED ]") " {} test(s) failed\n", fail);
+ for (auto* it = failed_head; it != nullptr; it = it->m_next)
+ {
+ asl::eprint(RED("[ FAILED ]") " {}\n", it->m_case_name);
+ }
}
return fail;
diff --git a/asl/tests/buffer_tests.cpp b/asl/tests/buffer_tests.cpp
index 15cc391..556eb2c 100644
--- a/asl/tests/buffer_tests.cpp
+++ b/asl/tests/buffer_tests.cpp
@@ -228,3 +228,58 @@ ASL_TEST(clear_destructor_heap)
ASL_TEST_EXPECT(d1 == true);
ASL_TEST_EXPECT(d2 == true);
}
+
+ASL_TEST(move_construct_from_heap)
+{
+ bool d[3]{};
+ asl::buffer<DestructorObserver> buf;
+ buf.push(&d[0]);
+ buf.push(&d[1]);
+ buf.push(&d[2]);
+
+ {
+ asl::buffer<DestructorObserver> buf2(ASL_MOVE(buf));
+ ASL_TEST_EXPECT(buf2.size() == 3);
+ ASL_TEST_EXPECT(d[0] == false);
+ ASL_TEST_EXPECT(d[1] == false);
+ ASL_TEST_EXPECT(d[2] == false);
+ }
+
+ ASL_TEST_EXPECT(buf.size() == 0);
+ ASL_TEST_EXPECT(d[0] == true);
+ ASL_TEST_EXPECT(d[1] == true);
+ ASL_TEST_EXPECT(d[2] == true);
+}
+
+ASL_TEST(move_construct_inline_trivial)
+{
+ asl::buffer<uint64_t> buf;
+ buf.push(1U);
+ buf.push(2U);
+
+ asl::buffer<uint64_t> buf2(ASL_MOVE(buf));
+ ASL_TEST_EXPECT(buf2[0] == 1U);
+ ASL_TEST_EXPECT(buf2[1] == 2U);
+
+ ASL_TEST_EXPECT(buf2.size() == 2);
+ ASL_TEST_EXPECT(buf.size() == 0);
+}
+
+ASL_TEST(move_construct_from_inline_non_trivial)
+{
+ bool d[2]{};
+ asl::buffer<DestructorObserver> buf;
+ buf.push(&d[0]);
+ buf.push(&d[1]);
+
+ {
+ asl::buffer<DestructorObserver> buf2(ASL_MOVE(buf));
+ ASL_TEST_EXPECT(buf2.size() == 2);
+ ASL_TEST_EXPECT(d[0] == false);
+ ASL_TEST_EXPECT(d[1] == false);
+ }
+
+ ASL_TEST_EXPECT(buf.size() == 0);
+ ASL_TEST_EXPECT(d[0] == true);
+ ASL_TEST_EXPECT(d[1] == true);
+}
diff --git a/asl/tests/test_types.hpp b/asl/tests/test_types.hpp
index f91afb3..1bcf72f 100644
--- a/asl/tests/test_types.hpp
+++ b/asl/tests/test_types.hpp
@@ -82,6 +82,7 @@ struct DestructorObserver
{
if (destroyed != nullptr)
{
+ ASL_ASSERT_RELEASE(*destroyed == false);
*destroyed = true;
}
}