VariantPool: store VariantSlots instead of chars

This commit is contained in:
Benoit Blanchon
2023-07-03 09:23:18 +02:00
parent 1d96826371
commit 0f511b873d
7 changed files with 51 additions and 40 deletions

View File

@ -32,15 +32,15 @@ TEST_CASE("JsonDocument assignment") {
SECTION("Copy assignment reallocates when capacity is smaller") {
JsonDocument doc1(4096, &spyingAllocator);
deserializeJson(doc1, "{\"hello\":\"world\"}");
JsonDocument doc2(8, &spyingAllocator);
deserializeJson(doc1, "[{\"hello\":\"world\"}]");
JsonDocument doc2(sizeofArray(1), &spyingAllocator);
spyingAllocator.clearLog();
doc2 = doc1;
REQUIRE(doc2.as<std::string>() == "{\"hello\":\"world\"}");
REQUIRE(doc2.as<std::string>() == "[{\"hello\":\"world\"}]");
REQUIRE(spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Deallocate(8)
AllocatorLog() << AllocatorLog::Deallocate(sizeofArray(1))
<< AllocatorLog::Allocate(4096)
<< AllocatorLog::Allocate(sizeofString(5)) // hello
<< AllocatorLog::Allocate(sizeofString(5)) // world
@ -68,7 +68,7 @@ TEST_CASE("JsonDocument assignment") {
{
JsonDocument doc1(4096, &spyingAllocator);
doc1.set(std::string("The size of this string is 32!!"));
JsonDocument doc2(8, &spyingAllocator);
JsonDocument doc2(128, &spyingAllocator);
doc2 = std::move(doc1);
@ -78,8 +78,8 @@ TEST_CASE("JsonDocument assignment") {
REQUIRE(spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(4096)
<< AllocatorLog::Allocate(sizeofString(31))
<< AllocatorLog::Allocate(8)
<< AllocatorLog::Deallocate(8)
<< AllocatorLog::Allocate(128)
<< AllocatorLog::Deallocate(128)
<< AllocatorLog::Deallocate(sizeofString(31))
<< AllocatorLog::Deallocate(4096));
}

View File

@ -8,6 +8,7 @@
#include "Allocators.hpp"
using ArduinoJson::detail::addPadding;
using ArduinoJson::detail::sizeofObject;
using ArduinoJson::detail::sizeofString;
TEST_CASE("JsonDocument constructor") {
@ -66,8 +67,8 @@ TEST_CASE("JsonDocument constructor") {
JsonDocument doc2(obj, &spyingAllocator);
REQUIRE(doc2.as<std::string>() == "{\"hello\":\"world\"}");
REQUIRE(spyingAllocator.log() == AllocatorLog() << AllocatorLog::Allocate(
addPadding(doc1.memoryUsage())));
REQUIRE(spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofObject(1)));
}
SECTION("Construct from JsonArray") {
@ -89,9 +90,9 @@ TEST_CASE("JsonDocument constructor") {
JsonDocument doc2(doc1.as<JsonVariant>(), &spyingAllocator);
REQUIRE(doc2.as<std::string>() == "hello");
REQUIRE(
spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(addPadding(doc1.memoryUsage()))
<< AllocatorLog::Allocate(sizeofString(5)));
REQUIRE(spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(
sizeofString(5)) // TODO: remove
<< AllocatorLog::Allocate(sizeofString(5)));
}
}

View File

@ -2,6 +2,7 @@
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#include <ArduinoJson/Memory/Alignment.hpp>
#include <ArduinoJson/Memory/ResourceManager.hpp>
#include <ArduinoJson/Memory/VariantPoolImpl.hpp>
#include <catch.hpp>

View File

@ -5,6 +5,7 @@
#pragma once
#include <ArduinoJson/Collection/CollectionData.hpp>
#include <ArduinoJson/Memory/Alignment.hpp>
#include <ArduinoJson/Strings/StringAdapters.hpp>
#include <ArduinoJson/Variant/VariantCompare.hpp>
#include <ArduinoJson/Variant/VariantData.hpp>

View File

@ -4,7 +4,6 @@
#pragma once
#include <ArduinoJson/Memory/Alignment.hpp>
#include <ArduinoJson/Memory/Allocator.hpp>
#include <ArduinoJson/Memory/StringPool.hpp>
#include <ArduinoJson/Memory/VariantPool.hpp>
@ -22,7 +21,7 @@ class ResourceManager {
ResourceManager(size_t capa,
Allocator* allocator = DefaultAllocator::instance())
: allocator_(allocator), overflowed_(false) {
variantPool_.create(addPadding(capa), allocator);
variantPool_.create(capa, allocator);
}
~ResourceManager() {
@ -48,8 +47,8 @@ class ResourceManager {
}
void reallocPool(size_t requiredSize) {
size_t capa = addPadding(requiredSize);
if (capa == capacity())
size_t capa = VariantPool::bytesToSlots(requiredSize);
if (capa == variantPool_.capacity())
return;
variantPool_.destroy(allocator_);
variantPool_.create(requiredSize, allocator_);
@ -57,11 +56,11 @@ class ResourceManager {
// Gets the capacity of the memoryPool in bytes
size_t capacity() const {
return variantPool_.capacity();
return VariantPool::slotsToBytes(variantPool_.capacity());
}
size_t size() const {
return variantPool_.usage() + stringPool_.size();
return VariantPool::slotsToBytes(variantPool_.usage()) + stringPool_.size();
}
bool overflowed() const {

View File

@ -14,7 +14,7 @@ class VariantSlot;
class VariantPool {
public:
~VariantPool() {
ARDUINOJSON_ASSERT(data_ == nullptr);
ARDUINOJSON_ASSERT(slots_ == nullptr);
}
VariantPool& operator=(VariantPool&& src) {
@ -22,8 +22,8 @@ class VariantPool {
src.capacity_ = 0;
usage_ = src.usage_;
src.usage_ = 0;
data_ = src.data_;
src.data_ = nullptr;
slots_ = src.slots_;
src.slots_ = nullptr;
return *this;
}
@ -36,12 +36,13 @@ class VariantPool {
size_t capacity() const;
size_t usage() const;
static size_t sizeForCapacity(size_t);
static size_t bytesToSlots(size_t);
static size_t slotsToBytes(size_t);
private:
size_t capacity_ = 0;
size_t usage_ = 0;
char* data_ = nullptr;
VariantSlot* slots_ = nullptr;
};
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@ -10,40 +10,40 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
inline void VariantPool::create(size_t cap, Allocator* allocator) {
ARDUINOJSON_ASSERT(data_ == nullptr);
ARDUINOJSON_ASSERT(slots_ == nullptr);
if (!cap)
return;
data_ = reinterpret_cast<char*>(allocator->allocate(cap));
if (data_) {
capacity_ = cap;
slots_ = reinterpret_cast<VariantSlot*>(allocator->allocate(cap));
if (slots_) {
capacity_ = bytesToSlots(cap);
usage_ = 0;
}
}
inline void VariantPool::destroy(Allocator* allocator) {
if (data_)
allocator->deallocate(data_);
data_ = nullptr;
if (slots_)
allocator->deallocate(slots_);
slots_ = nullptr;
capacity_ = 0;
usage_ = 0;
}
inline ptrdiff_t VariantPool::shrinkToFit(Allocator* allocator) {
auto originalPool = data_;
data_ = reinterpret_cast<char*>(allocator->reallocate(data_, usage_));
if (data_)
auto originalPool = slots_;
slots_ = reinterpret_cast<VariantSlot*>(
allocator->reallocate(slots_, slotsToBytes(usage_)));
if (slots_)
capacity_ = usage_;
return data_ - originalPool;
return reinterpret_cast<char*>(slots_) -
reinterpret_cast<char*>(originalPool);
}
inline VariantSlot* VariantPool::allocVariant() {
if (!data_)
if (!slots_)
return nullptr;
if (usage_ + sizeof(VariantSlot) > capacity_)
if (usage_ + 1 > capacity_)
return nullptr;
auto p = data_ + usage_;
usage_ += sizeof(VariantSlot);
return new (p) VariantSlot;
return new (&slots_[usage_++]) VariantSlot;
}
inline size_t VariantPool::usage() const {
@ -58,4 +58,12 @@ inline void VariantPool::clear() {
usage_ = 0;
}
inline size_t VariantPool::bytesToSlots(size_t n) {
return n / sizeof(VariantSlot);
}
inline size_t VariantPool::slotsToBytes(size_t n) {
return n * sizeof(VariantSlot);
}
ARDUINOJSON_END_PRIVATE_NAMESPACE