From af164f9af26d0c64d2e8210039b99e4f191acdaa Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Sun, 8 Dec 2024 23:58:43 +0100 Subject: Some careful work on buffer --- asl/buffer.hpp | 87 +++++++++++++++++++++++++++++++++++++++++++--- asl/tests/buffer_tests.cpp | 18 ++++++++++ 2 files changed, 101 insertions(+), 4 deletions(-) (limited to 'asl') diff --git a/asl/buffer.hpp b/asl/buffer.hpp index abf29fe..b45d5d8 100644 --- a/asl/buffer.hpp +++ b/asl/buffer.hpp @@ -3,6 +3,7 @@ #include "asl/meta.hpp" #include "asl/allocator.hpp" #include "asl/annotations.hpp" +#include "asl/memory.hpp" namespace asl { @@ -14,17 +15,47 @@ class buffer T* m_data{}; isize_t m_capacity{}; - // bit 63 : 0 = on heap, 1 = inline + static constexpr size_t kOnHeapMask = 0x8000'0000'0000'0000ULL; + + // bit 63 : 1 = on heap, 0 = inline // bits [62:56] : size when inline - // bits [52:0] : size when on heap - size_t m_size_encoded{}; + // bits [62:0] : size when on heap + size_t m_size_encoded_{}; ASL_NO_UNIQUE_ADDRESS Allocator m_allocator; static_assert(align_of <= align_of); static_assert(align_of == align_of); static_assert(align_of == align_of); - + + constexpr size_t load_size_encoded() const + { + size_t s{}; + asl::memcpy(&s, &m_size_encoded_, sizeof(size_t)); + return s; + } + + static constexpr bool is_on_heap(size_t size_encoded) + { + return (size_encoded & kOnHeapMask) != 0; + } + + static constexpr isize_t decode_size(size_t size_encoded) + { + if constexpr (kInlineCapacity == 0) + { + return is_on_heap(size_encoded) + ? static_cast(size_encoded & (~kOnHeapMask)) + : 0; + } + else + { + return is_on_heap(size_encoded) + ? static_cast(size_encoded & (~kOnHeapMask)) + : static_cast(size_encoded >> 56); + } + } + public: static constexpr isize_t kInlineCapacity = []() { @@ -40,6 +71,54 @@ public: explicit constexpr buffer(Allocator allocator) : m_allocator{ASL_MOVE(allocator)} {} + + constexpr isize_t size() const + { + return decode_size(load_size_encoded()); + } + + constexpr isize_t capacity() const + { + if constexpr (kInlineCapacity == 0) + { + return m_capacity; + } + else + { + return is_on_heap(load_size_encoded()) + ? m_capacity + : kInlineCapacity; + } + } + + // @Todo(C++23) Use deducing this + const T* data() const + { + if constexpr (kInlineCapacity == 0) + { + return m_data; + } + else + { + return is_on_heap(load_size_encoded()) + ? m_data + : reinterpret_cast(this); + } + } + + T* data() + { + if constexpr (kInlineCapacity == 0) + { + return m_data; + } + else + { + return is_on_heap(load_size_encoded()) + ? m_data + : reinterpret_cast(this); + } + } }; } // namespace asl diff --git a/asl/tests/buffer_tests.cpp b/asl/tests/buffer_tests.cpp index 133a549..2d23b2f 100644 --- a/asl/tests/buffer_tests.cpp +++ b/asl/tests/buffer_tests.cpp @@ -2,7 +2,25 @@ #include +struct Big +{ + uint64_t data[8]; +}; + static_assert(asl::buffer::kInlineCapacity == 5); static_assert(asl::buffer::kInlineCapacity == 2); static_assert(asl::buffer::kInlineCapacity == 23); +static_assert(asl::buffer::kInlineCapacity == 0); + +ASL_TEST(default_size) +{ + asl::buffer b1; + ASL_TEST_EXPECT(b1.size() == 0); + ASL_TEST_EXPECT(b1.capacity() == 5); + ASL_TEST_EXPECT(static_cast(b1.data()) == &b1); + asl::buffer b2; + ASL_TEST_EXPECT(b2.size() == 0); + ASL_TEST_EXPECT(b2.capacity() == 0); + ASL_TEST_EXPECT(b2.data() == nullptr); +} -- cgit