Make MemoryPool generic

This commit is contained in:
Benoit Blanchon
2024-08-25 14:57:35 +02:00
parent 2be24eded8
commit 362201241f
18 changed files with 178 additions and 192 deletions

View File

@ -265,12 +265,14 @@ class TimebombAllocator : public ArduinoJson::Allocator {
} // namespace } // namespace
inline size_t sizeofPoolList(size_t n = ARDUINOJSON_INITIAL_POOL_COUNT) { inline size_t sizeofPoolList(size_t n = ARDUINOJSON_INITIAL_POOL_COUNT) {
return sizeof(ArduinoJson::detail::MemoryPool) * n; using namespace ArduinoJson::detail;
return sizeof(MemoryPool<VariantData>) * n;
} }
inline size_t sizeofPool( inline size_t sizeofPool(
ArduinoJson::detail::SlotCount n = ARDUINOJSON_POOL_CAPACITY) { ArduinoJson::detail::SlotCount n = ARDUINOJSON_POOL_CAPACITY) {
return ArduinoJson::detail::MemoryPool::slotsToBytes(n); using namespace ArduinoJson::detail;
return MemoryPool<VariantData>::slotsToBytes(n);
} }
inline size_t sizeofStringBuffer(size_t iteration = 1) { inline size_t sizeofStringBuffer(size_t iteration = 1) {

View File

@ -2,7 +2,6 @@
// Copyright © 2014-2024, Benoit BLANCHON // Copyright © 2014-2024, Benoit BLANCHON
// MIT License // MIT License
#include <ArduinoJson/Memory/MemoryPoolImpl.hpp>
#include <ArduinoJson/Memory/StringBuilder.hpp> #include <ArduinoJson/Memory/StringBuilder.hpp>
#include <catch.hpp> #include <catch.hpp>

View File

@ -2,7 +2,6 @@
// Copyright © 2014-2024, Benoit BLANCHON // Copyright © 2014-2024, Benoit BLANCHON
// MIT License // MIT License
#include <ArduinoJson/Memory/MemoryPoolImpl.hpp>
#include <ArduinoJson/Memory/ResourceManager.hpp> #include <ArduinoJson/Memory/ResourceManager.hpp>
#include <ArduinoJson/Memory/ResourceManagerImpl.hpp> #include <ArduinoJson/Memory/ResourceManagerImpl.hpp>
#include <ArduinoJson/Strings/StringAdapters.hpp> #include <ArduinoJson/Strings/StringAdapters.hpp>

View File

@ -2,7 +2,6 @@
// Copyright © 2014-2024, Benoit BLANCHON // Copyright © 2014-2024, Benoit BLANCHON
// MIT License // MIT License
#include <ArduinoJson/Memory/MemoryPoolImpl.hpp>
#include <ArduinoJson/Memory/ResourceManager.hpp> #include <ArduinoJson/Memory/ResourceManager.hpp>
#include <ArduinoJson/Strings/StringAdapters.hpp> #include <ArduinoJson/Strings/StringAdapters.hpp>
#include <catch.hpp> #include <catch.hpp>

View File

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

View File

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

View File

@ -3,7 +3,6 @@
// MIT License // MIT License
#include <ArduinoJson/Memory/Alignment.hpp> #include <ArduinoJson/Memory/Alignment.hpp>
#include <ArduinoJson/Memory/MemoryPoolImpl.hpp>
#include <ArduinoJson/Memory/ResourceManager.hpp> #include <ArduinoJson/Memory/ResourceManager.hpp>
#include <ArduinoJson/Memory/ResourceManagerImpl.hpp> #include <ArduinoJson/Memory/ResourceManagerImpl.hpp>
#include <catch.hpp> #include <catch.hpp>

View File

@ -36,13 +36,13 @@
#include "ArduinoJson/Array/ElementProxy.hpp" #include "ArduinoJson/Array/ElementProxy.hpp"
#include "ArduinoJson/Array/Utilities.hpp" #include "ArduinoJson/Array/Utilities.hpp"
#include "ArduinoJson/Collection/CollectionImpl.hpp" #include "ArduinoJson/Collection/CollectionImpl.hpp"
#include "ArduinoJson/Memory/MemoryPoolImpl.hpp"
#include "ArduinoJson/Memory/ResourceManagerImpl.hpp" #include "ArduinoJson/Memory/ResourceManagerImpl.hpp"
#include "ArduinoJson/Object/MemberProxy.hpp" #include "ArduinoJson/Object/MemberProxy.hpp"
#include "ArduinoJson/Object/ObjectImpl.hpp" #include "ArduinoJson/Object/ObjectImpl.hpp"
#include "ArduinoJson/Variant/ConverterImpl.hpp" #include "ArduinoJson/Variant/ConverterImpl.hpp"
#include "ArduinoJson/Variant/JsonVariantCopier.hpp" #include "ArduinoJson/Variant/JsonVariantCopier.hpp"
#include "ArduinoJson/Variant/VariantCompare.hpp" #include "ArduinoJson/Variant/VariantCompare.hpp"
#include "ArduinoJson/Variant/VariantImpl.hpp"
#include "ArduinoJson/Variant/VariantRefBaseImpl.hpp" #include "ArduinoJson/Variant/VariantRefBaseImpl.hpp"
#include "ArduinoJson/Json/JsonDeserializer.hpp" #include "ArduinoJson/Json/JsonDeserializer.hpp"

View File

@ -4,7 +4,7 @@
#pragma once #pragma once
#include <ArduinoJson/Memory/ResourceManager.hpp> #include <ArduinoJson/Memory/MemoryPool.hpp>
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
#include <ArduinoJson/Polyfills/assert.hpp> #include <ArduinoJson/Polyfills/assert.hpp>
@ -13,6 +13,7 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
class VariantData; class VariantData;
class ResourceManager;
class CollectionIterator { class CollectionIterator {
friend class CollectionData; friend class CollectionData;
@ -78,9 +79,7 @@ class CollectionData {
using iterator = CollectionIterator; using iterator = CollectionIterator;
iterator createIterator(const ResourceManager* resources) const { iterator createIterator(const ResourceManager* resources) const;
return iterator(resources->getVariant(head_), head_);
}
size_t size(const ResourceManager*) const; size_t size(const ResourceManager*) const;
size_t nesting(const ResourceManager*) const; size_t nesting(const ResourceManager*) const;
@ -98,15 +97,17 @@ class CollectionData {
} }
protected: protected:
void appendOne(VariantWithId slot, const ResourceManager* resources); void appendOne(SlotWithId<VariantData> slot,
void appendPair(VariantWithId key, VariantWithId value, const ResourceManager* resources);
void appendPair(SlotWithId<VariantData> key, SlotWithId<VariantData> value,
const ResourceManager* resources); const ResourceManager* resources);
void removeOne(iterator it, ResourceManager* resources); void removeOne(iterator it, ResourceManager* resources);
void removePair(iterator it, ResourceManager* resources); void removePair(iterator it, ResourceManager* resources);
private: private:
VariantWithId getPreviousSlot(VariantData*, const ResourceManager*) const; SlotWithId<VariantData> getPreviousSlot(VariantData*,
const ResourceManager*) const;
}; };
inline const VariantData* collectionToVariant( inline const VariantData* collectionToVariant(

View File

@ -25,7 +25,12 @@ inline void CollectionIterator::next(const ResourceManager* resources) {
nextId_ = slot_->next(); nextId_ = slot_->next();
} }
inline void CollectionData::appendOne(VariantWithId slot, inline CollectionData::iterator CollectionData::createIterator(
const ResourceManager* resources) const {
return iterator(resources->getVariant(head_), head_);
}
inline void CollectionData::appendOne(SlotWithId<VariantData> slot,
const ResourceManager* resources) { const ResourceManager* resources) {
if (tail_ != NULL_SLOT) { if (tail_ != NULL_SLOT) {
auto tail = resources->getVariant(tail_); auto tail = resources->getVariant(tail_);
@ -37,7 +42,8 @@ inline void CollectionData::appendOne(VariantWithId slot,
} }
} }
inline void CollectionData::appendPair(VariantWithId key, VariantWithId value, inline void CollectionData::appendPair(SlotWithId<VariantData> key,
SlotWithId<VariantData> value,
const ResourceManager* resources) { const ResourceManager* resources) {
key->setNext(value.id()); key->setNext(value.id());
@ -57,22 +63,22 @@ inline void CollectionData::clear(ResourceManager* resources) {
auto currId = next; auto currId = next;
auto slot = resources->getVariant(next); auto slot = resources->getVariant(next);
next = slot->next(); next = slot->next();
resources->freeVariant(VariantWithId(slot, currId)); resources->freeVariant(SlotWithId<VariantData>(slot, currId));
} }
head_ = NULL_SLOT; head_ = NULL_SLOT;
tail_ = NULL_SLOT; tail_ = NULL_SLOT;
} }
inline VariantWithId CollectionData::getPreviousSlot( inline SlotWithId<VariantData> CollectionData::getPreviousSlot(
VariantData* target, const ResourceManager* resources) const { VariantData* target, const ResourceManager* resources) const {
auto prev = VariantWithId(); auto prev = SlotWithId<VariantData>();
auto currentId = head_; auto currentId = head_;
while (currentId != NULL_SLOT) { while (currentId != NULL_SLOT) {
auto currentSlot = resources->getVariant(currentId); auto currentSlot = resources->getVariant(currentId);
if (currentSlot == target) if (currentSlot == target)
break; break;
prev = VariantWithId(currentSlot, currentId); prev = SlotWithId<VariantData>(currentSlot, currentId);
currentId = currentSlot->next(); currentId = currentSlot->next();
} }
return prev; return prev;

View File

@ -10,15 +10,15 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
class VariantData;
using SlotId = uint_t<ARDUINOJSON_SLOT_ID_SIZE * 8>; using SlotId = uint_t<ARDUINOJSON_SLOT_ID_SIZE * 8>;
using SlotCount = SlotId; using SlotCount = SlotId;
const SlotId NULL_SLOT = SlotId(-1); const SlotId NULL_SLOT = SlotId(-1);
template <typename T>
class SlotWithId { class SlotWithId {
public: public:
SlotWithId() : slot_(nullptr), id_(NULL_SLOT) {} SlotWithId() : slot_(nullptr), id_(NULL_SLOT) {}
SlotWithId(VariantData* slot, SlotId id) : slot_(slot), id_(id) { SlotWithId(T* slot, SlotId id) : slot_(slot), id_(id) {
ARDUINOJSON_ASSERT((slot == nullptr) == (id == NULL_SLOT)); ARDUINOJSON_ASSERT((slot == nullptr) == (id == NULL_SLOT));
} }
@ -30,38 +30,81 @@ class SlotWithId {
return id_; return id_;
} }
VariantData* ptr() const { T* ptr() const {
return slot_; return slot_;
} }
VariantData* operator->() { T* operator->() const {
ARDUINOJSON_ASSERT(slot_ != nullptr); ARDUINOJSON_ASSERT(slot_ != nullptr);
return slot_; return slot_;
} }
private: private:
VariantData* slot_; T* slot_;
SlotId id_; SlotId id_;
}; };
template <typename T>
class MemoryPool { class MemoryPool {
public: public:
void create(SlotCount cap, Allocator* allocator); void create(SlotCount cap, Allocator* allocator) {
void destroy(Allocator* allocator); ARDUINOJSON_ASSERT(cap > 0);
slots_ = reinterpret_cast<T*>(allocator->allocate(slotsToBytes(cap)));
capacity_ = slots_ ? cap : 0;
usage_ = 0;
}
SlotWithId allocSlot(); void destroy(Allocator* allocator) {
VariantData* getSlot(SlotId id) const; if (slots_)
void clear(); allocator->deallocate(slots_);
void shrinkToFit(Allocator*); slots_ = nullptr;
SlotCount usage() const; capacity_ = 0;
usage_ = 0;
}
static SlotCount bytesToSlots(size_t); SlotWithId<T> allocSlot() {
static size_t slotsToBytes(SlotCount); if (!slots_)
return {};
if (usage_ >= capacity_)
return {};
auto index = usage_++;
return {slots_ + index, SlotId(index)};
}
T* getSlot(SlotId id) const {
ARDUINOJSON_ASSERT(id < usage_);
return slots_ + id;
}
void clear() {
usage_ = 0;
}
void shrinkToFit(Allocator* allocator) {
auto newSlots = reinterpret_cast<T*>(
allocator->reallocate(slots_, slotsToBytes(usage_)));
if (newSlots) {
slots_ = newSlots;
capacity_ = usage_;
}
}
SlotCount usage() const {
return usage_;
}
static SlotCount bytesToSlots(size_t n) {
return static_cast<SlotCount>(n / sizeof(T));
}
static size_t slotsToBytes(SlotCount n) {
return n * sizeof(T);
}
private: private:
SlotCount capacity_; SlotCount capacity_;
SlotCount usage_; SlotCount usage_;
VariantData* slots_; T* slots_;
}; };
ARDUINOJSON_END_PRIVATE_NAMESPACE ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@ -1,81 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2024, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Memory/MemoryPool.hpp>
#include <ArduinoJson/Variant/VariantData.hpp>
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
inline void MemoryPool::create(SlotCount cap, Allocator* allocator) {
ARDUINOJSON_ASSERT(cap > 0);
slots_ =
reinterpret_cast<VariantData*>(allocator->allocate(slotsToBytes(cap)));
capacity_ = slots_ ? cap : 0;
usage_ = 0;
}
inline void MemoryPool::destroy(Allocator* allocator) {
if (slots_)
allocator->deallocate(slots_);
slots_ = nullptr;
capacity_ = 0;
usage_ = 0;
}
inline void MemoryPool::shrinkToFit(Allocator* allocator) {
auto newSlots = reinterpret_cast<VariantData*>(
allocator->reallocate(slots_, slotsToBytes(usage_)));
if (newSlots) {
slots_ = newSlots;
capacity_ = usage_;
}
}
inline SlotWithId MemoryPool::allocSlot() {
if (!slots_)
return {};
if (usage_ >= capacity_)
return {};
auto index = usage_++;
auto slot = &slots_[index];
return {slot, SlotId(index)};
}
inline VariantData* MemoryPool::getSlot(SlotId id) const {
ARDUINOJSON_ASSERT(id < usage_);
return &slots_[id];
}
inline SlotCount MemoryPool::usage() const {
return usage_;
}
inline void MemoryPool::clear() {
usage_ = 0;
}
inline SlotCount MemoryPool::bytesToSlots(size_t n) {
return static_cast<SlotCount>(n / sizeof(VariantData));
}
inline size_t MemoryPool::slotsToBytes(SlotCount n) {
return n * sizeof(VariantData);
}
inline SlotWithId MemoryPoolList::allocFromFreeList() {
ARDUINOJSON_ASSERT(freeList_ != NULL_SLOT);
auto id = freeList_;
auto slot = getSlot(freeList_);
freeList_ = reinterpret_cast<FreeSlot*>(slot)->next;
return {slot, id};
}
inline void MemoryPoolList::freeSlot(SlotWithId slot) {
reinterpret_cast<FreeSlot*>(slot.ptr())->next = freeList_;
freeList_ = slot.id();
}
ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@ -14,12 +14,17 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
using PoolCount = SlotId; using PoolCount = SlotId;
template <typename T>
class MemoryPoolList { class MemoryPoolList {
struct FreeSlot { struct FreeSlot {
SlotId next; SlotId next;
}; };
static_assert(sizeof(FreeSlot) <= sizeof(T), "T is too small");
public: public:
using Pool = MemoryPool<T>;
MemoryPoolList() = default; MemoryPoolList() = default;
~MemoryPoolList() { ~MemoryPoolList() {
@ -74,7 +79,7 @@ class MemoryPoolList {
return *this; return *this;
} }
SlotWithId allocSlot(Allocator* allocator) { SlotWithId<T> allocSlot(Allocator* allocator) {
// try to allocate from free list // try to allocate from free list
if (freeList_ != NULL_SLOT) { if (freeList_ != NULL_SLOT) {
return allocFromFreeList(); return allocFromFreeList();
@ -95,9 +100,12 @@ class MemoryPoolList {
return allocFromLastPool(); return allocFromLastPool();
} }
void freeSlot(SlotWithId slot); void freeSlot(SlotWithId<T> slot) {
reinterpret_cast<FreeSlot*>(slot.ptr())->next = freeList_;
freeList_ = slot.id();
}
VariantData* getSlot(SlotId id) const { T* getSlot(SlotId id) const {
if (id == NULL_SLOT) if (id == NULL_SLOT)
return nullptr; return nullptr;
auto poolIndex = SlotId(id / ARDUINOJSON_POOL_CAPACITY); auto poolIndex = SlotId(id / ARDUINOJSON_POOL_CAPACITY);
@ -125,21 +133,31 @@ class MemoryPoolList {
return total; return total;
} }
size_t size() const {
return Pool::slotsToBytes(usage());
}
void shrinkToFit(Allocator* allocator) { void shrinkToFit(Allocator* allocator) {
if (count_ > 0) if (count_ > 0)
pools_[count_ - 1].shrinkToFit(allocator); pools_[count_ - 1].shrinkToFit(allocator);
if (pools_ != preallocatedPools_ && count_ != capacity_) { if (pools_ != preallocatedPools_ && count_ != capacity_) {
pools_ = static_cast<MemoryPool*>( pools_ = static_cast<Pool*>(
allocator->reallocate(pools_, count_ * sizeof(MemoryPool))); allocator->reallocate(pools_, count_ * sizeof(Pool)));
ARDUINOJSON_ASSERT(pools_ != nullptr); // realloc to smaller can't fail ARDUINOJSON_ASSERT(pools_ != nullptr); // realloc to smaller can't fail
capacity_ = count_; capacity_ = count_;
} }
} }
private: private:
SlotWithId allocFromFreeList(); SlotWithId<T> allocFromFreeList() {
ARDUINOJSON_ASSERT(freeList_ != NULL_SLOT);
auto id = freeList_;
auto slot = getSlot(freeList_);
freeList_ = reinterpret_cast<FreeSlot*>(slot)->next;
return {slot, id};
}
SlotWithId allocFromLastPool() { SlotWithId<T> allocFromLastPool() {
ARDUINOJSON_ASSERT(count_ > 0); ARDUINOJSON_ASSERT(count_ > 0);
auto poolIndex = SlotId(count_ - 1); auto poolIndex = SlotId(count_ - 1);
auto slot = pools_[poolIndex].allocSlot(); auto slot = pools_[poolIndex].allocSlot();
@ -149,7 +167,7 @@ class MemoryPoolList {
SlotId(poolIndex * ARDUINOJSON_POOL_CAPACITY + slot.id())}; SlotId(poolIndex * ARDUINOJSON_POOL_CAPACITY + slot.id())};
} }
MemoryPool* addPool(Allocator* allocator) { Pool* addPool(Allocator* allocator) {
if (count_ == capacity_ && !increaseCapacity(allocator)) if (count_ == capacity_ && !increaseCapacity(allocator))
return nullptr; return nullptr;
auto pool = &pools_[count_++]; auto pool = &pools_[count_++];
@ -167,24 +185,23 @@ class MemoryPoolList {
auto newCapacity = PoolCount(capacity_ * 2); auto newCapacity = PoolCount(capacity_ * 2);
if (pools_ == preallocatedPools_) { if (pools_ == preallocatedPools_) {
newPools = allocator->allocate(newCapacity * sizeof(MemoryPool)); newPools = allocator->allocate(newCapacity * sizeof(Pool));
if (!newPools) if (!newPools)
return false; return false;
memcpy(newPools, preallocatedPools_, sizeof(preallocatedPools_)); memcpy(newPools, preallocatedPools_, sizeof(preallocatedPools_));
} else { } else {
newPools = newPools = allocator->reallocate(pools_, newCapacity * sizeof(Pool));
allocator->reallocate(pools_, newCapacity * sizeof(MemoryPool));
if (!newPools) if (!newPools)
return false; return false;
} }
pools_ = static_cast<MemoryPool*>(newPools); pools_ = static_cast<Pool*>(newPools);
capacity_ = newCapacity; capacity_ = newCapacity;
return true; return true;
} }
MemoryPool preallocatedPools_[ARDUINOJSON_INITIAL_POOL_COUNT]; Pool preallocatedPools_[ARDUINOJSON_INITIAL_POOL_COUNT];
MemoryPool* pools_ = preallocatedPools_; Pool* pools_ = preallocatedPools_;
PoolCount count_ = 0; PoolCount count_ = 0;
PoolCount capacity_ = ARDUINOJSON_INITIAL_POOL_COUNT; PoolCount capacity_ = ARDUINOJSON_INITIAL_POOL_COUNT;
SlotId freeList_ = NULL_SLOT; SlotId freeList_ = NULL_SLOT;

View File

@ -10,10 +10,10 @@
#include <ArduinoJson/Polyfills/assert.hpp> #include <ArduinoJson/Polyfills/assert.hpp>
#include <ArduinoJson/Polyfills/utility.hpp> #include <ArduinoJson/Polyfills/utility.hpp>
#include <ArduinoJson/Strings/StringAdapters.hpp> #include <ArduinoJson/Strings/StringAdapters.hpp>
#include <ArduinoJson/Variant/VariantData.hpp>
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
class MemoryPool;
class VariantData; class VariantData;
class VariantWithId; class VariantWithId;
@ -42,16 +42,16 @@ class ResourceManager {
} }
size_t size() const { size_t size() const {
return MemoryPool::slotsToBytes(variantPools_.usage()) + stringPool_.size(); return variantPools_.size() + stringPool_.size();
} }
bool overflowed() const { bool overflowed() const {
return overflowed_; return overflowed_;
} }
VariantWithId allocVariant(); SlotWithId<VariantData> allocVariant();
void freeVariant(VariantWithId slot); void freeVariant(SlotWithId<VariantData> slot);
VariantData* getVariant(SlotId id) const; VariantData* getVariant(SlotId id) const;
@ -112,7 +112,7 @@ class ResourceManager {
Allocator* allocator_; Allocator* allocator_;
bool overflowed_; bool overflowed_;
StringPool stringPool_; StringPool stringPool_;
MemoryPoolList variantPools_; MemoryPoolList<VariantData> variantPools_;
}; };
ARDUINOJSON_END_PRIVATE_NAMESPACE ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@ -10,7 +10,7 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
inline VariantWithId ResourceManager::allocVariant() { inline SlotWithId<VariantData> ResourceManager::allocVariant() {
auto p = variantPools_.allocSlot(allocator_); auto p = variantPools_.allocSlot(allocator_);
if (!p) { if (!p) {
overflowed_ = true; overflowed_ = true;
@ -19,7 +19,7 @@ inline VariantWithId ResourceManager::allocVariant() {
return {new (p.ptr()) VariantData, p.id()}; return {new (p.ptr()) VariantData, p.id()};
} }
inline void ResourceManager::freeVariant(VariantWithId variant) { inline void ResourceManager::freeVariant(SlotWithId<VariantData> variant) {
variant->setNull(this); variant->setNull(this);
variantPools_.freeSlot(variant); variantPools_.freeSlot(variant);
} }

View File

@ -12,8 +12,6 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
class MemoryPool;
class StringPool { class StringPool {
public: public:
StringPool() = default; StringPool() = default;

View File

@ -408,14 +408,7 @@ class VariantData {
} }
template <typename T> template <typename T>
void setRawString(SerializedValue<T> value, ResourceManager* resources) { void setRawString(SerializedValue<T> value, ResourceManager* resources);
release(resources);
auto dup = resources->saveString(adaptString(value.data(), value.size()));
if (dup)
setRawString(dup);
else
setNull();
}
template <typename T> template <typename T>
static void setRawString(VariantData* var, SerializedValue<T> value, static void setRawString(VariantData* var, SerializedValue<T> value,
@ -426,25 +419,7 @@ class VariantData {
} }
template <typename TAdaptedString> template <typename TAdaptedString>
bool setString(TAdaptedString value, ResourceManager* resources) { bool setString(TAdaptedString value, ResourceManager* resources);
setNull(resources);
if (value.isNull())
return false;
if (value.isLinked()) {
setLinkedString(value.data());
return true;
}
auto dup = resources->saveString(value);
if (dup) {
setOwnedString(dup);
return true;
}
return false;
}
bool setString(StringNode* s, ResourceManager*) { bool setString(StringNode* s, ResourceManager*) {
setOwnedString(s); setOwnedString(s);
@ -524,30 +499,7 @@ class VariantData {
} }
private: private:
void release(ResourceManager* resources) { void release(ResourceManager* resources);
if (type_ & OWNED_VALUE_BIT)
resources->dereferenceString(content_.asOwnedString->data);
auto collection = asCollection();
if (collection)
collection->clear(resources);
}
};
class VariantWithId : public SlotWithId {
public:
VariantWithId() {}
VariantWithId(VariantData* data, SlotId id)
: SlotWithId(reinterpret_cast<VariantData*>(data), id) {}
VariantData* ptr() {
return reinterpret_cast<VariantData*>(SlotWithId::ptr());
}
VariantData* operator->() {
ARDUINOJSON_ASSERT(ptr() != nullptr);
return ptr();
}
}; };
ARDUINOJSON_END_PRIVATE_NAMESPACE ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@ -0,0 +1,54 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2024, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Memory/ResourceManager.hpp>
#include <ArduinoJson/Variant/VariantData.hpp>
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <typename T>
inline void VariantData::setRawString(SerializedValue<T> value,
ResourceManager* resources) {
release(resources);
auto dup = resources->saveString(adaptString(value.data(), value.size()));
if (dup)
setRawString(dup);
else
setNull();
}
template <typename TAdaptedString>
inline bool VariantData::setString(TAdaptedString value,
ResourceManager* resources) {
setNull(resources);
if (value.isNull())
return false;
if (value.isLinked()) {
setLinkedString(value.data());
return true;
}
auto dup = resources->saveString(value);
if (dup) {
setOwnedString(dup);
return true;
}
return false;
}
inline void VariantData::release(ResourceManager* resources) {
if (type_ & OWNED_VALUE_BIT)
resources->dereferenceString(content_.asOwnedString->data);
auto collection = asCollection();
if (collection)
collection->clear(resources);
}
ARDUINOJSON_END_PRIVATE_NAMESPACE