summaryrefslogtreecommitdiff
path: root/asl
diff options
context:
space:
mode:
authorSteven Le Rouzic <steven.lerouzic@gmail.com>2025-01-01 19:40:06 +0100
committerSteven Le Rouzic <steven.lerouzic@gmail.com>2025-01-01 19:40:06 +0100
commit7e66d8e7e50060553be837b021aef1d83d0252bd (patch)
tree855dd59082f1aacda77a58054e75a4522887f240 /asl
parent22131693e1892c5477c998ab63bf476d152b17cb (diff)
Implement move assign for buffer
Diffstat (limited to 'asl')
-rw-r--r--asl/buffer.hpp35
-rw-r--r--asl/tests/buffer_tests.cpp97
2 files changed, 121 insertions, 11 deletions
diff --git a/asl/buffer.hpp b/asl/buffer.hpp
index 84284bc..276222d 100644
--- a/asl/buffer.hpp
+++ b/asl/buffer.hpp
@@ -111,15 +111,8 @@ private:
}
}
-public:
- constexpr buffer() requires default_constructible<Allocator> = default;
-
- explicit constexpr buffer(Allocator allocator)
- : m_allocator{ASL_MOVE(allocator)}
- {}
-
- constexpr buffer(buffer&& other)
- : buffer(ASL_MOVE(other.m_allocator))
+ // NOLINTNEXTLINE(*-rvalue-reference-param-not-moved)
+ void move_from_other(buffer&& other)
{
if (other.is_on_heap())
{
@@ -142,6 +135,30 @@ public:
other.set_size_inline(0);
}
+public:
+ constexpr buffer() requires default_constructible<Allocator> = default;
+
+ explicit constexpr buffer(Allocator allocator)
+ : m_allocator{ASL_MOVE(allocator)}
+ {}
+
+ constexpr buffer(buffer&& other)
+ : buffer(ASL_MOVE(other.m_allocator))
+ {
+ move_from_other(ASL_MOVE(other));
+ }
+
+ constexpr buffer& operator=(buffer&& other)
+ {
+ if (&other == this) { return *this; }
+
+ destroy();
+ m_allocator = ASL_MOVE(other.m_allocator);
+ move_from_other(ASL_MOVE(other));
+
+ return *this;
+ }
+
~buffer()
{
destroy();
diff --git a/asl/tests/buffer_tests.cpp b/asl/tests/buffer_tests.cpp
index 556eb2c..cc34420 100644
--- a/asl/tests/buffer_tests.cpp
+++ b/asl/tests/buffer_tests.cpp
@@ -191,13 +191,14 @@ ASL_TEST(clear)
ASL_TEST_EXPECT(b.size() == 0);
}
+static_assert(asl::buffer<DestructorObserver>::kInlineCapacity == 2);
+
ASL_TEST(clear_destructor_small)
{
bool d0 = false;
bool d1 = false;
asl::buffer<DestructorObserver> buf;
- static_assert(asl::buffer<DestructorObserver>::kInlineCapacity >= 2);
buf.push(&d0);
buf.push(&d1);
@@ -214,7 +215,6 @@ ASL_TEST(clear_destructor_heap)
bool d2 = false;
asl::buffer<DestructorObserver> buf;
- static_assert(asl::buffer<DestructorObserver>::kInlineCapacity < 3);
buf.push(&d0);
buf.push(&d1);
@@ -283,3 +283,96 @@ ASL_TEST(move_construct_from_inline_non_trivial)
ASL_TEST_EXPECT(d[0] == true);
ASL_TEST_EXPECT(d[1] == true);
}
+
+ASL_TEST(move_assign_from_heap)
+{
+ bool d[6]{};
+
+ {
+ asl::buffer<DestructorObserver> buf;
+ asl::buffer<DestructorObserver> buf2;
+
+ buf.push(&d[0]);
+ buf.push(&d[1]);
+ buf.push(&d[2]);
+
+ buf2.push(&d[3]);
+ buf2.push(&d[4]);
+ buf2.push(&d[5]);
+
+ ASL_TEST_EXPECT(d[0] == false);
+ ASL_TEST_EXPECT(d[1] == false);
+ ASL_TEST_EXPECT(d[2] == false);
+ ASL_TEST_EXPECT(d[3] == false);
+ ASL_TEST_EXPECT(d[4] == false);
+ ASL_TEST_EXPECT(d[5] == false);
+
+ buf2 = ASL_MOVE(buf);
+
+ ASL_TEST_EXPECT(buf.size() == 0);
+ 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(d[3] == true);
+ ASL_TEST_EXPECT(d[4] == true);
+ ASL_TEST_EXPECT(d[5] == true);
+ }
+
+ ASL_TEST_EXPECT(d[0] == true);
+ ASL_TEST_EXPECT(d[1] == true);
+ ASL_TEST_EXPECT(d[2] == true);
+ ASL_TEST_EXPECT(d[3] == true);
+ ASL_TEST_EXPECT(d[4] == true);
+ ASL_TEST_EXPECT(d[5] == true);
+}
+
+ASL_TEST(move_assign_trivial_heap_to_inline)
+{
+ isize_t alloc_count = 0;
+ asl::buffer<int64_t, CounterAllocator> buf{CounterAllocator(&alloc_count)};
+ asl::buffer<int64_t, CounterAllocator> buf2{CounterAllocator(&alloc_count)};
+
+ buf.push(1);
+ buf.push(2);
+ ASL_TEST_EXPECT(alloc_count == 0);
+
+ buf2.push(3);
+ buf2.push(4);
+ buf2.push(5);
+ ASL_TEST_EXPECT(alloc_count == 1);
+
+ buf = ASL_MOVE(buf2);
+ ASL_TEST_EXPECT(alloc_count == 1);
+
+ ASL_TEST_EXPECT(buf.size() == 3);
+ ASL_TEST_EXPECT(buf2.size() == 0);
+ ASL_TEST_EXPECT(buf[0] == 3);
+ ASL_TEST_EXPECT(buf[1] == 4);
+ ASL_TEST_EXPECT(buf[2] == 5);
+}
+
+ASL_TEST(move_assign_trivial_inline_to_heap)
+{
+ isize_t alloc_count = 0;
+ asl::buffer<int64_t, CounterAllocator> buf{CounterAllocator(&alloc_count)};
+ asl::buffer<int64_t, CounterAllocator> buf2{CounterAllocator(&alloc_count)};
+
+ buf.push(1);
+ buf.push(2);
+ ASL_TEST_EXPECT(alloc_count == 0);
+
+ buf2.push(3);
+ buf2.push(4);
+ buf2.push(5);
+ ASL_TEST_EXPECT(alloc_count == 1);
+
+ buf2 = ASL_MOVE(buf);
+ ASL_TEST_EXPECT(alloc_count == 1);
+
+ ASL_TEST_EXPECT(buf.size() == 0);
+ ASL_TEST_EXPECT(buf2.size() == 2);
+ ASL_TEST_EXPECT(buf2[0] == 1);
+ ASL_TEST_EXPECT(buf2[1] == 2);
+}