From 7e66d8e7e50060553be837b021aef1d83d0252bd Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Wed, 1 Jan 2025 19:40:06 +0100 Subject: Implement move assign for buffer --- asl/buffer.hpp | 35 ++++++++++++----- asl/tests/buffer_tests.cpp | 97 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 121 insertions(+), 11 deletions(-) (limited to 'asl') 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 = 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 = 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::kInlineCapacity == 2); + ASL_TEST(clear_destructor_small) { bool d0 = false; bool d1 = false; asl::buffer buf; - static_assert(asl::buffer::kInlineCapacity >= 2); buf.push(&d0); buf.push(&d1); @@ -214,7 +215,6 @@ ASL_TEST(clear_destructor_heap) bool d2 = false; asl::buffer buf; - static_assert(asl::buffer::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 buf; + asl::buffer 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 buf{CounterAllocator(&alloc_count)}; + asl::buffer 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 buf{CounterAllocator(&alloc_count)}; + asl::buffer 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); +} -- cgit