From 12b864491fe9750e9fbe09e354374bb441941761 Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Thu, 2 Jan 2025 19:08:40 +0100 Subject: Optimize buffer move with compatible allocators --- asl/buffer.hpp | 51 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 12 deletions(-) (limited to 'asl/buffer.hpp') diff --git a/asl/buffer.hpp b/asl/buffer.hpp index a616011..ca371d2 100644 --- a/asl/buffer.hpp +++ b/asl/buffer.hpp @@ -86,11 +86,21 @@ private: constexpr T* push_uninit() { isize_t sz = size(); - reserve_capacity(sz + 1); - set_size(sz + 1); + resize_uninit(sz + 1); return data() + sz; } + constexpr void resize_uninit(isize_t new_size) + { + isize_t old_size = size(); + if (!trivially_destructible && new_size < old_size) + { + destroy_n(data() + new_size, old_size - new_size); + } + reserve_capacity(new_size); + set_size(new_size); + } + constexpr void set_size_inline(isize_t new_size) { ASL_ASSERT(new_size >= 0 && new_size <= kInlineCapacity); @@ -112,22 +122,38 @@ private: } // NOLINTNEXTLINE(*-rvalue-reference-param-not-moved) - void move_from_other(buffer&& other) + void move_from_other(buffer&& other, bool assign) { - ASL_ASSERT(size() == 0 && !is_on_heap()); - if (other.is_on_heap()) { + destroy(); m_data = other.m_data; m_capacity = other.m_capacity; store_size_encoded(other.load_size_encoded()); } else if (trivially_move_constructible) { + destroy(); asl::memcpy(this, &other, kInlineRegionSize); } + else if (!assign || m_allocator == other.m_allocator) + { + isize_t other_n = other.size(); + isize_t this_n = size(); + resize_uninit(other_n); + if (other_n < this_n) + { + relocate_assign_n(data(), other.data(), other_n); + } + else + { + relocate_assign_n(data(), other.data(), this_n); + relocate_uninit_n(data() + this_n, other.data() + this_n, other_n - this_n); + } + } else { + destroy(); isize_t n = other.size(); ASL_ASSERT(n <= kInlineCapacity); relocate_uninit_n(data(), other.data(), n); @@ -135,6 +161,11 @@ private: } other.set_size_inline(0); + + if (assign) + { + m_allocator = ASL_MOVE(other.m_allocator); + } } public: @@ -147,17 +178,13 @@ public: constexpr buffer(buffer&& other) : buffer(ASL_MOVE(other.m_allocator)) { - move_from_other(ASL_MOVE(other)); + move_from_other(ASL_MOVE(other), false); } constexpr buffer& operator=(buffer&& other) { if (&other == this) { return *this; } - - destroy(); - m_allocator = ASL_MOVE(other.m_allocator); - move_from_other(ASL_MOVE(other)); - + move_from_other(ASL_MOVE(other), true); return *this; } @@ -166,7 +193,7 @@ public: destroy(); } - // @Todo Copy/move constructor & assignment + // @Todo Copy constructor & assignment constexpr isize_t size() const { -- cgit