mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-28 09:47:31 +02:00
Make MemoryPool
generic
This commit is contained in:
@ -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) {
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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"
|
||||||
|
@ -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(
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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
|
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,6 @@
|
|||||||
|
|
||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
class MemoryPool;
|
|
||||||
|
|
||||||
class StringPool {
|
class StringPool {
|
||||||
public:
|
public:
|
||||||
StringPool() = default;
|
StringPool() = default;
|
||||||
|
@ -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
|
||||||
|
54
src/ArduinoJson/Variant/VariantImpl.hpp
Normal file
54
src/ArduinoJson/Variant/VariantImpl.hpp
Normal 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
|
Reference in New Issue
Block a user