mana::Arena: fixes and segment limit and tests
This commit is contained in:
parent
fa897ea233
commit
6d93197f86
3 changed files with 103 additions and 13 deletions
|
@ -1,4 +1,4 @@
|
|||
set(MVLC_NNG_MNODE_WARN_FLAGS -Wall -Wextra -Wpedantic)
|
||||
set(MVLC_NNG_MNODE_WARN_FLAGS -Wall -Wextra -Wpedantic -Werror=return-type)
|
||||
|
||||
add_library(mesytec-mnode mnode_nng.cc mnode_nng_async.cc mnode_nng_proto.cc)
|
||||
target_include_directories(mesytec-mnode
|
||||
|
@ -13,7 +13,7 @@ add_subdirectory(tools)
|
|||
if (MNODE_BUILD_TESTS)
|
||||
function (add_mnode_gtest name)
|
||||
add_executable(test_${name} ${name}.test.cc)
|
||||
target_link_libraries(test_${name} PRIVATE mesytec-mnode GTest::gtest_main)
|
||||
target_link_libraries(test_${name} PRIVATE mesytec-mnode GTest::gtest_main spdlog)
|
||||
add_test(NAME name COMMAND $<TARGET_FILE:test_${name}>)
|
||||
endfunction()
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ class Arena
|
|||
public:
|
||||
static constexpr size_t initial_segment_size = 1u << 20;
|
||||
static constexpr size_t default_pad = 8;
|
||||
static constexpr size_t default_max_segments = 1;
|
||||
|
||||
Arena() = default;
|
||||
~Arena() = default;
|
||||
|
@ -32,19 +33,27 @@ class Arena
|
|||
|
||||
if (!segment_ || segment_->free() < required)
|
||||
{
|
||||
// could waste complete segments if required > default size of 1u << 20 but that's fine
|
||||
// for now
|
||||
segment_ =
|
||||
&segments_.emplace_back(Arena::Segment(std::max(required, initial_segment_size)));
|
||||
if (segment_count() < max_segments())
|
||||
{
|
||||
// could waste complete segments if required > default size of 1u << 20 but that's
|
||||
// fine for now
|
||||
segment_ = &segments_.emplace_back(
|
||||
Arena::Segment(std::max(required, initial_segment_size)));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
assert(segment_ && segment_->free() >= required);
|
||||
|
||||
std::memset(segment_->cur(), 0, required);
|
||||
auto result = segment_->cur();
|
||||
std::memset(result, 0, required);
|
||||
segment_->used += required;
|
||||
++allocations_;
|
||||
pad_waste_ += pad_waste;
|
||||
return segment_->cur();
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T> T *push_t(size_t count = 1)
|
||||
|
@ -53,11 +62,11 @@ class Arena
|
|||
return reinterpret_cast<T *>(push_size(sizeof(T) * count));
|
||||
}
|
||||
|
||||
const char *push_cstr(const std::string &str)
|
||||
char *push_cstr(const std::string &str)
|
||||
{
|
||||
auto mem = push_size(str.size() + 1);
|
||||
std::memcpy(mem, str.c_str(), str.size());
|
||||
return reinterpret_cast<const char *>(mem);
|
||||
return reinterpret_cast<char *>(mem);
|
||||
}
|
||||
|
||||
void reset()
|
||||
|
@ -69,6 +78,7 @@ class Arena
|
|||
pad_waste_ = 0;
|
||||
}
|
||||
|
||||
size_t max_segments() const { return max_segments_; }
|
||||
size_t allocations() const { return allocations_; }
|
||||
size_t pad_waste() const { return pad_waste_; }
|
||||
size_t segment_count() const { return segments_.size(); }
|
||||
|
@ -83,9 +93,13 @@ class Arena
|
|||
{
|
||||
auto accu = [](size_t sum, const Segment &seg) { return sum + seg.used; };
|
||||
return std::accumulate(std::begin(segments_), std::end(segments_), static_cast<size_t>(0u),
|
||||
accu) - pad_waste_;
|
||||
accu) -
|
||||
pad_waste_;
|
||||
}
|
||||
|
||||
const u8 *cur_begin() const { return segment_ ? segment_->data.data() : nullptr; }
|
||||
const u8 *cur_end() const { return segment_ ? segment_->cur() : nullptr; }
|
||||
|
||||
private:
|
||||
Arena(const Arena &) = delete;
|
||||
Arena &operator=(const Arena &) = delete;
|
||||
|
@ -105,6 +119,7 @@ class Arena
|
|||
void reset() { used = 0; }
|
||||
};
|
||||
|
||||
size_t max_segments_ = default_max_segments;
|
||||
std::list<Segment> segments_;
|
||||
Segment *segment_ = nullptr;
|
||||
size_t allocations_ = 0;
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include <mesytec-mnode/mnode_cpp_types.h>
|
||||
#include "internal/mana_arena.h"
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "tools/mana_replay_api.h"
|
||||
#include "tools/mana_lib.hpp"
|
||||
|
||||
using namespace mesytec::mnode;
|
||||
|
||||
TEST(mnode_mana, Arena)
|
||||
TEST(mnode_mana_arena, push_reset_push)
|
||||
{
|
||||
mana::Arena arena;
|
||||
|
||||
|
@ -14,7 +17,7 @@ TEST(mnode_mana, Arena)
|
|||
ASSERT_EQ(arena.capacity(), 0);
|
||||
ASSERT_EQ(arena.used(), 0);
|
||||
|
||||
for (size_t i=0; i<10; ++i)
|
||||
for (size_t i = 0; i < 10; ++i)
|
||||
{
|
||||
auto mem = arena.push_size(mana::Arena::default_pad + 2);
|
||||
ASSERT_NE(mem, nullptr);
|
||||
|
@ -33,4 +36,76 @@ TEST(mnode_mana, Arena)
|
|||
ASSERT_GE(arena.segment_count(), 1);
|
||||
ASSERT_GE(arena.capacity(), 10 * (mana::Arena::default_pad + 2));
|
||||
ASSERT_EQ(arena.used(), 0);
|
||||
|
||||
for (size_t i = 0; i < 10; ++i)
|
||||
{
|
||||
auto mem = arena.push_size(mana::Arena::default_pad + 2);
|
||||
ASSERT_NE(mem, nullptr);
|
||||
}
|
||||
|
||||
ASSERT_EQ(arena.allocations(), 10);
|
||||
ASSERT_GE(arena.pad_waste(), 0);
|
||||
ASSERT_GE(arena.segment_count(), 1);
|
||||
ASSERT_GE(arena.capacity(), 10 * (mana::Arena::default_pad + 2));
|
||||
ASSERT_EQ(arena.used(), 10 * (mana::Arena::default_pad + 2));
|
||||
}
|
||||
|
||||
TEST(mnode_mana_offset_ptr, basic)
|
||||
{
|
||||
using namespace mana;
|
||||
|
||||
struct OffsetPtrTest
|
||||
{
|
||||
u32 a;
|
||||
mana_offset_ptr_t ptr0; // &a
|
||||
mana_offset_ptr_t ptr1; // &b
|
||||
u32 b;
|
||||
};
|
||||
|
||||
mana::Arena arena;
|
||||
|
||||
auto t = arena.push_t<OffsetPtrTest>();
|
||||
t->a = 42;
|
||||
t->b = 43;
|
||||
|
||||
set(t->ptr0, &t->a);
|
||||
set(t->ptr1, &t->b);
|
||||
|
||||
ASSERT_EQ(get<u32>(t->ptr0), &t->a);
|
||||
ASSERT_EQ(get<u32>(t->ptr1), &t->b);
|
||||
ASSERT_EQ(get<double>(t->ptr0), nullptr);
|
||||
ASSERT_EQ(get<double>(t->ptr1), nullptr);
|
||||
}
|
||||
|
||||
TEST(mnode_mana_offset_ptr, strings)
|
||||
{
|
||||
using namespace mana;
|
||||
|
||||
struct OffsetPtrTest
|
||||
{
|
||||
mana_offset_ptr_t ptr0;
|
||||
mana_offset_ptr_t ptr1;
|
||||
};
|
||||
|
||||
mana::Arena arena;
|
||||
|
||||
auto t = arena.push_t<OffsetPtrTest>();
|
||||
|
||||
auto s0 = arena.push_cstr("hello");
|
||||
auto s1 = arena.push_cstr("world");
|
||||
|
||||
spdlog::info("&t->ptr0={}, &t->ptr1={}", fmt::ptr(&t->ptr0), fmt::ptr(&t->ptr1));
|
||||
spdlog::info("s0={} @ {}, s1={} @ {}", s0, fmt::ptr(s0), s1, fmt::ptr(s1));
|
||||
|
||||
set(t->ptr0, s0);
|
||||
set(t->ptr1, s1);
|
||||
|
||||
ASSERT_EQ(get<char>(t->ptr0), std::string("hello"));
|
||||
ASSERT_EQ(get<char>(t->ptr1), std::string("world"));
|
||||
ASSERT_EQ(get<double>(t->ptr0), nullptr);
|
||||
ASSERT_EQ(get<double>(t->ptr1), nullptr);
|
||||
|
||||
set(t->ptr0, nullptr);
|
||||
ASSERT_EQ(get<char>(t->ptr0), nullptr);
|
||||
ASSERT_EQ(get<char>(t->ptr1), std::string("world"));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue