Buffer clear & destructor

This commit is contained in:
2024-12-30 00:05:38 +01:00
parent 7e8cd10685
commit 739f532104
2 changed files with 84 additions and 15 deletions

View File

@ -12,10 +12,18 @@ namespace asl
template<is_object T, allocator Allocator = DefaultAllocator> template<is_object T, allocator Allocator = DefaultAllocator>
class buffer class buffer
{ {
T* m_data{}; T* m_data{};
isize_t m_capacity{}; isize_t m_capacity{};
static constexpr size_t kOnHeapMask = 0x8000'0000'0000'0000ULL;
// bit 63 : 1 = on heap, 0 = inline
// bits [62:56] : size when inline
// bits [62:0] : size when on heap
size_t m_size_encoded_{};
ASL_NO_UNIQUE_ADDRESS Allocator m_allocator;
public: public:
static constexpr isize_t kInlineCapacity = []() { static constexpr isize_t kInlineCapacity = []() {
// 1 byte is used for size inline in m_size_encoded. // 1 byte is used for size inline in m_size_encoded.
@ -26,15 +34,6 @@ public:
}(); }();
private: private:
static constexpr size_t kOnHeapMask = 0x8000'0000'0000'0000ULL;
// bit 63 : 1 = on heap, 0 = inline
// bits [62:56] : size when inline
// bits [62:0] : size when on heap
size_t m_size_encoded_{};
ASL_NO_UNIQUE_ADDRESS Allocator m_allocator;
static_assert(align_of<T> <= align_of<T*>); static_assert(align_of<T> <= align_of<T*>);
static_assert(align_of<T*> == align_of<isize_t>); static_assert(align_of<T*> == align_of<isize_t>);
static_assert(align_of<T*> == align_of<size_t>); static_assert(align_of<T*> == align_of<size_t>);
@ -114,10 +113,17 @@ public:
: m_allocator{ASL_MOVE(allocator)} : m_allocator{ASL_MOVE(allocator)}
{} {}
// @Todo Destructor ~buffer()
// @Todo clear {
clear();
if (is_on_heap() && m_data != nullptr)
{
auto current_layout = layout::array<T>(m_capacity);
m_allocator.dealloc(m_data, current_layout);
}
}
// @Todo Copy/move constructor & assignment // @Todo Copy/move constructor & assignment
// @Todo Do leak checks on Linux
constexpr isize_t size() const constexpr isize_t size() const
{ {
@ -136,6 +142,15 @@ public:
} }
} }
void clear()
{
isize_t current_size = size();
if (current_size == 0) { return; }
destruct_n(data(), current_size);
set_size(0);
}
void reserve_capacity(isize_t new_capacity) void reserve_capacity(isize_t new_capacity)
{ {
ASL_ASSERT(new_capacity >= 0); ASL_ASSERT(new_capacity >= 0);

View File

@ -1,7 +1,7 @@
#include "asl/buffer.hpp" #include "asl/buffer.hpp"
#include "asl/print.hpp"
#include "asl/testing/testing.hpp" #include "asl/testing/testing.hpp"
#include "asl/tests/test_types.hpp"
struct Big struct Big
{ {
@ -171,4 +171,58 @@ ASL_TEST(push_move)
ASL_TEST_EXPECT(b[4].moved == 0); ASL_TEST_EXPECT(b[4].moved == 0);
} }
// @Todo Test push with non trivial move (non copy) types ASL_TEST(clear)
{
asl::buffer<int32_t> b;
ASL_TEST_EXPECT(b.size() == 0);
b.push(1);
b.push(2);
b.push(3);
b.push(4);
b.push(5);
b.push(6);
b.push(7);
ASL_TEST_EXPECT(b.size() == 7);
b.clear();
ASL_TEST_EXPECT(b.size() == 0);
}
ASL_TEST(clear_destructor_small)
{
bool d0 = false;
bool d1 = false;
asl::buffer<DestructorObserver> buf;
static_assert(asl::buffer<DestructorObserver>::kInlineCapacity >= 2);
buf.push(&d0);
buf.push(&d1);
buf.clear();
ASL_TEST_EXPECT(d0 == true);
ASL_TEST_EXPECT(d1 == true);
}
ASL_TEST(clear_destructor_heap)
{
bool d0 = false;
bool d1 = false;
bool d2 = false;
asl::buffer<DestructorObserver> buf;
static_assert(asl::buffer<DestructorObserver>::kInlineCapacity < 3);
buf.push(&d0);
buf.push(&d1);
buf.push(&d2);
ASL_TEST_EXPECT(d0 == false);
ASL_TEST_EXPECT(d1 == false);
ASL_TEST_EXPECT(d2 == false);
buf.clear();
ASL_TEST_EXPECT(d0 == true);
ASL_TEST_EXPECT(d1 == true);
ASL_TEST_EXPECT(d2 == true);
}