From b2eddfabffeb78fc5b49f9c17d70175d2dfed2e0 Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Tue, 31 Dec 2024 01:16:12 +0100 Subject: Some work on buffer move --- asl/allocator.hpp | 4 +++- asl/buffer.hpp | 59 +++++++++++++++++++++++++++++++++++++--------- asl/meta.hpp | 11 +++++++++ asl/tests/buffer_tests.cpp | 2 ++ asl/tests/format_tests.cpp | 4 ++-- 5 files changed, 66 insertions(+), 14 deletions(-) (limited to 'asl') diff --git a/asl/allocator.hpp b/asl/allocator.hpp index eb03e0f..5f8f9b6 100644 --- a/asl/allocator.hpp +++ b/asl/allocator.hpp @@ -7,7 +7,7 @@ namespace asl { template -concept allocator = moveable && +concept allocator = moveable && equality_comparable && requires(T& alloc, layout layout, void* ptr) { { alloc.alloc(layout) } -> same_as; @@ -21,6 +21,8 @@ public: static void* alloc(const layout&); static void* realloc(void* ptr, const layout& old, const layout& new_layout); static void dealloc(void* ptr, const layout&); + + constexpr bool operator==(const GlobalHeap&) const { return true; } }; static_assert(allocator); diff --git a/asl/buffer.hpp b/asl/buffer.hpp index d2226b1..9020a99 100644 --- a/asl/buffer.hpp +++ b/asl/buffer.hpp @@ -23,13 +23,15 @@ class buffer size_t m_size_encoded_{}; ASL_NO_UNIQUE_ADDRESS Allocator m_allocator; + + static constexpr isize_t kInlineRegionSize = size_of + size_of + size_of; public: static constexpr isize_t kInlineCapacity = []() { // 1 byte is used for size inline in m_size_encoded. // This is enough because we have at most 24 bytes available, // so 23 chars of capacity. - const isize_t available_size = size_of + size_of + size_of - 1; + const isize_t available_size = kInlineRegionSize - 1; return available_size / size_of; }(); @@ -89,20 +91,24 @@ private: return data() + sz; } + constexpr void set_size_inline(isize_t new_size) + { + ASL_ASSERT(new_size >= 0 && new_size <= kInlineCapacity); + size_t size_encoded = (load_size_encoded() & size_t{0x00ff'ffff'ffff'ffff}) | (bit_cast(new_size) << 56); + store_size_encoded(size_encoded); + } + constexpr void set_size(isize_t new_size) { ASL_ASSERT(new_size >= 0); ASL_ASSERT_RELEASE(new_size <= capacity()); - size_t size_encoded = load_size_encoded(); - if (kInlineCapacity == 0 || is_on_heap(size_encoded)) + if (kInlineCapacity == 0 || is_on_heap()) { store_size_encoded(encode_size_heap(new_size)); } else { - ASL_ASSERT(new_size <= kInlineCapacity); - size_encoded = (size_encoded & size_t{0x00ff'ffff'ffff'ffff}) | (bit_cast(new_size) << 56); - store_size_encoded(size_encoded); + set_size_inline(new_size); } } @@ -113,16 +119,34 @@ public: : m_allocator{ASL_MOVE(allocator)} {} - ~buffer() + constexpr buffer(buffer&& other) + : buffer(ASL_MOVE(other.m_allocator)) { - clear(); - if (is_on_heap() && m_data != nullptr) + if (other.is_on_heap()) + { + // @Todo Test this + destroy(); + m_data = other.m_data; + m_capacity = other.m_capacity; + set_size(other.size()); + } + else if (trivially_move_constructible) + { + // @Todo Test this + destroy(); + asl::memcpy(this, &other, kInlineRegionSize); + } + else { - auto current_layout = layout::array(m_capacity); - m_allocator.dealloc(m_data, current_layout); + // @Todo } } + ~buffer() + { + destroy(); + } + // @Todo Copy/move constructor & assignment constexpr isize_t size() const @@ -151,6 +175,19 @@ public: set_size(0); } + void destroy() + { + clear(); + if (is_on_heap()) + { + if (m_data != nullptr) + { + auto current_layout = layout::array(m_capacity); + m_allocator.dealloc(m_data, current_layout); + } + } + } + void reserve_capacity(isize_t new_capacity) { ASL_ASSERT(new_capacity >= 0); diff --git a/asl/meta.hpp b/asl/meta.hpp index 3fd76b4..133d2fb 100644 --- a/asl/meta.hpp +++ b/asl/meta.hpp @@ -164,6 +164,17 @@ template<> struct _is_floating_point_helper : true_type {}; template concept is_floating_point = _is_floating_point_helper>::value; +template +concept equality_comparable_with = requires (const un_cvref_t& a, const un_cvref_t& b) +{ + { a == b } -> same_as; + { b == a } -> same_as; + { a != b } -> same_as; + { b != a } -> same_as; +}; + +template concept equality_comparable = equality_comparable_with; + struct niche {}; template diff --git a/asl/tests/buffer_tests.cpp b/asl/tests/buffer_tests.cpp index 4c2d2c1..15cc391 100644 --- a/asl/tests/buffer_tests.cpp +++ b/asl/tests/buffer_tests.cpp @@ -46,6 +46,8 @@ struct CounterAllocator { asl::GlobalHeap::dealloc(ptr, layout); } + + constexpr bool operator==(const CounterAllocator&) const { return true; } }; static_assert(asl::allocator); diff --git a/asl/tests/format_tests.cpp b/asl/tests/format_tests.cpp index 042fcb4..8318757 100644 --- a/asl/tests/format_tests.cpp +++ b/asl/tests/format_tests.cpp @@ -12,7 +12,7 @@ class StringSink : public asl::Writer char* m_data{}; public: - ~StringSink() + ~StringSink() override { reset(); } @@ -24,7 +24,7 @@ public: asl::layout::array(m_current_len), asl::layout::array(m_current_len + str.size()))); - asl::memcpy(m_data + m_current_len, str.data(), str.size()); + asl::memcpy(m_data + m_current_len, str.data(), str.size()); // NOLINT m_current_len += str.size(); } -- cgit