From d90b36c009fa53864fa92e520deedea0be604ec6 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Sat, 17 Jun 2023 16:24:12 +0200 Subject: [PATCH] Extract `VariantPool` from `ResourceManager` --- extras/tests/ResourceManager/allocVariant.cpp | 2 +- extras/tests/ResourceManager/clear.cpp | 2 +- extras/tests/ResourceManager/size.cpp | 2 +- src/ArduinoJson.hpp | 1 + src/ArduinoJson/Memory/ResourceManager.hpp | 52 ++++++---------- src/ArduinoJson/Memory/VariantPool.hpp | 47 ++++++++++++++ src/ArduinoJson/Memory/VariantPoolImpl.hpp | 61 +++++++++++++++++++ src/ArduinoJson/Variant/VariantSlot.hpp | 10 --- 8 files changed, 132 insertions(+), 45 deletions(-) create mode 100644 src/ArduinoJson/Memory/VariantPool.hpp create mode 100644 src/ArduinoJson/Memory/VariantPoolImpl.hpp diff --git a/extras/tests/ResourceManager/allocVariant.cpp b/extras/tests/ResourceManager/allocVariant.cpp index 8d906a9f..9d2d6feb 100644 --- a/extras/tests/ResourceManager/allocVariant.cpp +++ b/extras/tests/ResourceManager/allocVariant.cpp @@ -3,7 +3,7 @@ // MIT License #include -#include +#include #include #include "Allocators.hpp" diff --git a/extras/tests/ResourceManager/clear.cpp b/extras/tests/ResourceManager/clear.cpp index 6060926c..a20c22f1 100644 --- a/extras/tests/ResourceManager/clear.cpp +++ b/extras/tests/ResourceManager/clear.cpp @@ -3,8 +3,8 @@ // MIT License #include +#include #include -#include #include using namespace ArduinoJson::detail; diff --git a/extras/tests/ResourceManager/size.cpp b/extras/tests/ResourceManager/size.cpp index 7509e325..9927b0bb 100644 --- a/extras/tests/ResourceManager/size.cpp +++ b/extras/tests/ResourceManager/size.cpp @@ -3,7 +3,7 @@ // MIT License #include -#include +#include #include using namespace ArduinoJson::detail; diff --git a/src/ArduinoJson.hpp b/src/ArduinoJson.hpp index 583ccddc..d9c43478 100644 --- a/src/ArduinoJson.hpp +++ b/src/ArduinoJson.hpp @@ -36,6 +36,7 @@ #include "ArduinoJson/Array/JsonArrayImpl.hpp" #include "ArduinoJson/Array/Utilities.hpp" #include "ArduinoJson/Collection/CollectionImpl.hpp" +#include "ArduinoJson/Memory/VariantPoolImpl.hpp" #include "ArduinoJson/Object/JsonObjectImpl.hpp" #include "ArduinoJson/Object/MemberProxy.hpp" #include "ArduinoJson/Variant/ConverterImpl.hpp" diff --git a/src/ArduinoJson/Memory/ResourceManager.hpp b/src/ArduinoJson/Memory/ResourceManager.hpp index 55f0fc2f..374d894a 100644 --- a/src/ArduinoJson/Memory/ResourceManager.hpp +++ b/src/ArduinoJson/Memory/ResourceManager.hpp @@ -7,24 +7,27 @@ #include #include #include +#include #include +#include #include ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE class VariantSlot; +class VariantPool; class ResourceManager { public: ResourceManager(size_t capa, Allocator* allocator = DefaultAllocator::instance()) : allocator_(allocator), overflowed_(false) { - allocPool(addPadding(capa)); + variantPool_.create(addPadding(capa), allocator); } ~ResourceManager() { deallocAllStrings(); - deallocPool(); + variantPool_.destroy(allocator_); } ResourceManager(const ResourceManager&) = delete; @@ -32,14 +35,10 @@ class ResourceManager { ResourceManager& operator=(ResourceManager&& src) { deallocAllStrings(); - deallocPool(); + variantPool_.destroy(allocator_); allocator_ = src.allocator_; - pool_ = src.pool_; - poolCapacity_ = src.poolCapacity_; - poolUsage_ = src.poolUsage_; + variantPool_ = detail::move(src.variantPool_); overflowed_ = src.overflowed_; - src.pool_ = nullptr; - src.poolCapacity_ = src.poolUsage_ = 0; strings_ = src.strings_; src.strings_ = nullptr; return *this; @@ -53,17 +52,17 @@ class ResourceManager { size_t capa = addPadding(requiredSize); if (capa == capacity()) return; - allocator_->deallocate(pool_); - allocPool(requiredSize); + variantPool_.destroy(allocator_); + variantPool_.create(requiredSize, allocator_); } // Gets the capacity of the memoryPool in bytes size_t capacity() const { - return poolCapacity_; + return variantPool_.capacity(); } size_t size() const { - size_t total = poolUsage_; + size_t total = variantPool_.usage(); for (auto node = strings_; node; node = node->next) total += sizeofString(node->length); return total; @@ -73,7 +72,12 @@ class ResourceManager { return overflowed_; } - VariantSlot* allocVariant(); + VariantSlot* allocVariant() { + auto p = variantPool_.allocVariant(); + if (!p) + overflowed_ = true; + return p; + } template StringNode* saveString(TAdaptedString str) { @@ -160,7 +164,7 @@ class ResourceManager { } void clear() { - poolUsage_ = 0; + variantPool_.clear(); overflowed_ = false; deallocAllStrings(); } @@ -171,10 +175,7 @@ class ResourceManager { } ptrdiff_t shrinkToFit() { - auto originalPoolAddress = pool_; - pool_ = reinterpret_cast(allocator_->reallocate(pool_, poolUsage_)); - poolCapacity_ = poolUsage_; - return pool_ - originalPoolAddress; + return variantPool_.shrinkToFit(allocator_); } private: @@ -186,23 +187,10 @@ class ResourceManager { } } - void allocPool(size_t capa) { - pool_ = capa ? reinterpret_cast(allocator_->allocate(capa)) : 0; - poolUsage_ = 0; - poolCapacity_ = pool_ ? capa : 0; - ARDUINOJSON_ASSERT(isAligned(pool_)); - } - - void deallocPool() { - if (pool_) - allocator_->deallocate(pool_); - } - Allocator* allocator_; - char* pool_; - size_t poolUsage_, poolCapacity_; bool overflowed_; StringNode* strings_ = nullptr; + VariantPool variantPool_; }; ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/src/ArduinoJson/Memory/VariantPool.hpp b/src/ArduinoJson/Memory/VariantPool.hpp new file mode 100644 index 00000000..a17ec329 --- /dev/null +++ b/src/ArduinoJson/Memory/VariantPool.hpp @@ -0,0 +1,47 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2023, Benoit BLANCHON +// MIT License + +#pragma once + +#include +#include + +ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE + +class VariantSlot; + +class VariantPool { + public: + ~VariantPool() { + ARDUINOJSON_ASSERT(data_ == nullptr); + } + + VariantPool& operator=(VariantPool&& src) { + capacity_ = src.capacity_; + src.capacity_ = 0; + usage_ = src.usage_; + src.usage_ = 0; + data_ = src.data_; + src.data_ = nullptr; + return *this; + } + + void create(size_t cap, Allocator* allocator); + void destroy(Allocator* allocator); + + VariantSlot* allocVariant(); + void clear(); + ptrdiff_t shrinkToFit(Allocator*); + size_t capacity() const; + size_t usage() const; + + static size_t sizeForCapacity(size_t); + + private: + size_t capacity_ = 0; + size_t usage_ = 0; + char* data_ = nullptr; +}; + +ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/src/ArduinoJson/Memory/VariantPoolImpl.hpp b/src/ArduinoJson/Memory/VariantPoolImpl.hpp new file mode 100644 index 00000000..dc575e6a --- /dev/null +++ b/src/ArduinoJson/Memory/VariantPoolImpl.hpp @@ -0,0 +1,61 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2023, Benoit BLANCHON +// MIT License + +#pragma once + +#include +#include + +ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE + +inline void VariantPool::create(size_t cap, Allocator* allocator) { + ARDUINOJSON_ASSERT(data_ == nullptr); + if (!cap) + return; + data_ = reinterpret_cast(allocator->allocate(cap)); + if (data_) { + capacity_ = cap; + usage_ = 0; + } +} + +inline void VariantPool::destroy(Allocator* allocator) { + if (data_) + allocator->deallocate(data_); + data_ = nullptr; + capacity_ = 0; + usage_ = 0; +} + +inline ptrdiff_t VariantPool::shrinkToFit(Allocator* allocator) { + auto originalPool = data_; + data_ = reinterpret_cast(allocator->reallocate(data_, usage_)); + if (data_) + capacity_ = usage_; + return data_ - originalPool; +} + +inline VariantSlot* VariantPool::allocVariant() { + if (!data_) + return nullptr; + if (usage_ + sizeof(VariantSlot) > capacity_) + return nullptr; + auto p = data_ + usage_; + usage_ += sizeof(VariantSlot); + return new (p) VariantSlot; +} + +inline size_t VariantPool::usage() const { + return usage_; +} + +inline size_t VariantPool::capacity() const { + return capacity_; +} + +inline void VariantPool::clear() { + usage_ = 0; +} + +ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/src/ArduinoJson/Variant/VariantSlot.hpp b/src/ArduinoJson/Variant/VariantSlot.hpp index 155f6e3e..6b0bb520 100644 --- a/src/ArduinoJson/Variant/VariantSlot.hpp +++ b/src/ArduinoJson/Variant/VariantSlot.hpp @@ -117,14 +117,4 @@ constexpr size_t sizeofObject(size_t n) { return n * sizeof(VariantSlot); } -inline VariantSlot* ResourceManager::allocVariant() { - if (poolUsage_ + sizeof(VariantSlot) > poolCapacity_) { - overflowed_ = true; - return 0; - } - auto p = pool_ + poolUsage_; - poolUsage_ += sizeof(VariantSlot); - return new (p) VariantSlot; -} - ARDUINOJSON_END_PRIVATE_NAMESPACE