diff options
author | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-12-31 01:16:12 +0100 |
---|---|---|
committer | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-12-31 01:16:12 +0100 |
commit | b2eddfabffeb78fc5b49f9c17d70175d2dfed2e0 (patch) | |
tree | 4f292d1608b0c5f4f60dab65af66a7c29156f425 /asl | |
parent | 739f53210466415affd5b0ebd5b3da5c251d232c (diff) |
Some work on buffer move
Diffstat (limited to 'asl')
-rw-r--r-- | asl/allocator.hpp | 4 | ||||
-rw-r--r-- | asl/buffer.hpp | 59 | ||||
-rw-r--r-- | asl/meta.hpp | 11 | ||||
-rw-r--r-- | asl/tests/buffer_tests.cpp | 2 | ||||
-rw-r--r-- | asl/tests/format_tests.cpp | 4 |
5 files changed, 66 insertions, 14 deletions
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<typename T>
-concept allocator = moveable<T> &&
+concept allocator = moveable<T> && equality_comparable<T> &&
requires(T& alloc, layout layout, void* ptr)
{
{ alloc.alloc(layout) } -> same_as<void*>;
@@ -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<GlobalHeap>);
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<T*> + size_of<isize_t> + size_of<size_t>;
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<T*> + size_of<isize_t> + size_of<size_t> - 1;
+ const isize_t available_size = kInlineRegionSize - 1;
return available_size / size_of<T>;
}();
@@ -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<size_t>(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<size_t>(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<T>)
+ {
+ // @Todo Test this
+ destroy();
+ asl::memcpy(this, &other, kInlineRegionSize);
+ }
+ else
{
- auto current_layout = layout::array<T>(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<T>(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<double> : true_type {}; template<typename T> concept is_floating_point = _is_floating_point_helper<un_cv_t<T>>::value;
+template<typename T, typename U>
+concept equality_comparable_with = requires (const un_cvref_t<T>& a, const un_cvref_t<T>& b)
+{
+ { a == b } -> same_as<bool>;
+ { b == a } -> same_as<bool>;
+ { a != b } -> same_as<bool>;
+ { b != a } -> same_as<bool>;
+};
+
+template<typename T> concept equality_comparable = equality_comparable_with<T, T>;
+
struct niche {};
template<typename T>
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<CounterAllocator>);
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<char>(m_current_len),
asl::layout::array<char>(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();
}
|