Buffer clear & destructor
This commit is contained in:
@ -12,10 +12,18 @@ namespace asl
|
||||
template<is_object T, allocator Allocator = DefaultAllocator>
|
||||
class buffer
|
||||
{
|
||||
|
||||
T* m_data{};
|
||||
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:
|
||||
static constexpr isize_t kInlineCapacity = []() {
|
||||
// 1 byte is used for size inline in m_size_encoded.
|
||||
@ -26,15 +34,6 @@ public:
|
||||
}();
|
||||
|
||||
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<isize_t>);
|
||||
static_assert(align_of<T*> == align_of<size_t>);
|
||||
@ -114,10 +113,17 @@ public:
|
||||
: m_allocator{ASL_MOVE(allocator)}
|
||||
{}
|
||||
|
||||
// @Todo Destructor
|
||||
// @Todo clear
|
||||
~buffer()
|
||||
{
|
||||
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 Do leak checks on Linux
|
||||
|
||||
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)
|
||||
{
|
||||
ASL_ASSERT(new_capacity >= 0);
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "asl/buffer.hpp"
|
||||
#include "asl/print.hpp"
|
||||
|
||||
#include "asl/testing/testing.hpp"
|
||||
#include "asl/tests/test_types.hpp"
|
||||
|
||||
struct Big
|
||||
{
|
||||
@ -171,4 +171,58 @@ ASL_TEST(push_move)
|
||||
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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user