Extract VariantPool from ResourceManager

This commit is contained in:
Benoit Blanchon
2023-06-17 16:24:12 +02:00
parent 8147625921
commit d90b36c009
8 changed files with 132 additions and 45 deletions

View File

@ -3,7 +3,7 @@
// MIT License // MIT License
#include <ArduinoJson/Memory/ResourceManager.hpp> #include <ArduinoJson/Memory/ResourceManager.hpp>
#include <ArduinoJson/Variant/VariantSlot.hpp> #include <ArduinoJson/Memory/VariantPoolImpl.hpp>
#include <catch.hpp> #include <catch.hpp>
#include "Allocators.hpp" #include "Allocators.hpp"

View File

@ -3,8 +3,8 @@
// MIT License // MIT License
#include <ArduinoJson/Memory/ResourceManager.hpp> #include <ArduinoJson/Memory/ResourceManager.hpp>
#include <ArduinoJson/Memory/VariantPoolImpl.hpp>
#include <ArduinoJson/Strings/StringAdapters.hpp> #include <ArduinoJson/Strings/StringAdapters.hpp>
#include <ArduinoJson/Variant/VariantSlot.hpp>
#include <catch.hpp> #include <catch.hpp>
using namespace ArduinoJson::detail; using namespace ArduinoJson::detail;

View File

@ -3,7 +3,7 @@
// MIT License // MIT License
#include <ArduinoJson/Memory/ResourceManager.hpp> #include <ArduinoJson/Memory/ResourceManager.hpp>
#include <ArduinoJson/Variant/VariantSlot.hpp> #include <ArduinoJson/Memory/VariantPoolImpl.hpp>
#include <catch.hpp> #include <catch.hpp>
using namespace ArduinoJson::detail; using namespace ArduinoJson::detail;

View File

@ -36,6 +36,7 @@
#include "ArduinoJson/Array/JsonArrayImpl.hpp" #include "ArduinoJson/Array/JsonArrayImpl.hpp"
#include "ArduinoJson/Array/Utilities.hpp" #include "ArduinoJson/Array/Utilities.hpp"
#include "ArduinoJson/Collection/CollectionImpl.hpp" #include "ArduinoJson/Collection/CollectionImpl.hpp"
#include "ArduinoJson/Memory/VariantPoolImpl.hpp"
#include "ArduinoJson/Object/JsonObjectImpl.hpp" #include "ArduinoJson/Object/JsonObjectImpl.hpp"
#include "ArduinoJson/Object/MemberProxy.hpp" #include "ArduinoJson/Object/MemberProxy.hpp"
#include "ArduinoJson/Variant/ConverterImpl.hpp" #include "ArduinoJson/Variant/ConverterImpl.hpp"

View File

@ -7,24 +7,27 @@
#include <ArduinoJson/Memory/Alignment.hpp> #include <ArduinoJson/Memory/Alignment.hpp>
#include <ArduinoJson/Memory/Allocator.hpp> #include <ArduinoJson/Memory/Allocator.hpp>
#include <ArduinoJson/Memory/StringNode.hpp> #include <ArduinoJson/Memory/StringNode.hpp>
#include <ArduinoJson/Memory/VariantPool.hpp>
#include <ArduinoJson/Polyfills/assert.hpp> #include <ArduinoJson/Polyfills/assert.hpp>
#include <ArduinoJson/Polyfills/utility.hpp>
#include <ArduinoJson/Strings/StringAdapters.hpp> #include <ArduinoJson/Strings/StringAdapters.hpp>
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
class VariantSlot; class VariantSlot;
class VariantPool;
class ResourceManager { class ResourceManager {
public: public:
ResourceManager(size_t capa, ResourceManager(size_t capa,
Allocator* allocator = DefaultAllocator::instance()) Allocator* allocator = DefaultAllocator::instance())
: allocator_(allocator), overflowed_(false) { : allocator_(allocator), overflowed_(false) {
allocPool(addPadding(capa)); variantPool_.create(addPadding(capa), allocator);
} }
~ResourceManager() { ~ResourceManager() {
deallocAllStrings(); deallocAllStrings();
deallocPool(); variantPool_.destroy(allocator_);
} }
ResourceManager(const ResourceManager&) = delete; ResourceManager(const ResourceManager&) = delete;
@ -32,14 +35,10 @@ class ResourceManager {
ResourceManager& operator=(ResourceManager&& src) { ResourceManager& operator=(ResourceManager&& src) {
deallocAllStrings(); deallocAllStrings();
deallocPool(); variantPool_.destroy(allocator_);
allocator_ = src.allocator_; allocator_ = src.allocator_;
pool_ = src.pool_; variantPool_ = detail::move(src.variantPool_);
poolCapacity_ = src.poolCapacity_;
poolUsage_ = src.poolUsage_;
overflowed_ = src.overflowed_; overflowed_ = src.overflowed_;
src.pool_ = nullptr;
src.poolCapacity_ = src.poolUsage_ = 0;
strings_ = src.strings_; strings_ = src.strings_;
src.strings_ = nullptr; src.strings_ = nullptr;
return *this; return *this;
@ -53,17 +52,17 @@ class ResourceManager {
size_t capa = addPadding(requiredSize); size_t capa = addPadding(requiredSize);
if (capa == capacity()) if (capa == capacity())
return; return;
allocator_->deallocate(pool_); variantPool_.destroy(allocator_);
allocPool(requiredSize); variantPool_.create(requiredSize, allocator_);
} }
// Gets the capacity of the memoryPool in bytes // Gets the capacity of the memoryPool in bytes
size_t capacity() const { size_t capacity() const {
return poolCapacity_; return variantPool_.capacity();
} }
size_t size() const { size_t size() const {
size_t total = poolUsage_; size_t total = variantPool_.usage();
for (auto node = strings_; node; node = node->next) for (auto node = strings_; node; node = node->next)
total += sizeofString(node->length); total += sizeofString(node->length);
return total; return total;
@ -73,7 +72,12 @@ class ResourceManager {
return overflowed_; return overflowed_;
} }
VariantSlot* allocVariant(); VariantSlot* allocVariant() {
auto p = variantPool_.allocVariant();
if (!p)
overflowed_ = true;
return p;
}
template <typename TAdaptedString> template <typename TAdaptedString>
StringNode* saveString(TAdaptedString str) { StringNode* saveString(TAdaptedString str) {
@ -160,7 +164,7 @@ class ResourceManager {
} }
void clear() { void clear() {
poolUsage_ = 0; variantPool_.clear();
overflowed_ = false; overflowed_ = false;
deallocAllStrings(); deallocAllStrings();
} }
@ -171,10 +175,7 @@ class ResourceManager {
} }
ptrdiff_t shrinkToFit() { ptrdiff_t shrinkToFit() {
auto originalPoolAddress = pool_; return variantPool_.shrinkToFit(allocator_);
pool_ = reinterpret_cast<char*>(allocator_->reallocate(pool_, poolUsage_));
poolCapacity_ = poolUsage_;
return pool_ - originalPoolAddress;
} }
private: private:
@ -186,23 +187,10 @@ class ResourceManager {
} }
} }
void allocPool(size_t capa) {
pool_ = capa ? reinterpret_cast<char*>(allocator_->allocate(capa)) : 0;
poolUsage_ = 0;
poolCapacity_ = pool_ ? capa : 0;
ARDUINOJSON_ASSERT(isAligned(pool_));
}
void deallocPool() {
if (pool_)
allocator_->deallocate(pool_);
}
Allocator* allocator_; Allocator* allocator_;
char* pool_;
size_t poolUsage_, poolCapacity_;
bool overflowed_; bool overflowed_;
StringNode* strings_ = nullptr; StringNode* strings_ = nullptr;
VariantPool variantPool_;
}; };
ARDUINOJSON_END_PRIVATE_NAMESPACE ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@ -0,0 +1,47 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Memory/ResourceManager.hpp>
#include <ArduinoJson/Polyfills/assert.hpp>
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

View File

@ -0,0 +1,61 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Memory/VariantPool.hpp>
#include <ArduinoJson/Variant/VariantSlot.hpp>
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
inline void VariantPool::create(size_t cap, Allocator* allocator) {
ARDUINOJSON_ASSERT(data_ == nullptr);
if (!cap)
return;
data_ = reinterpret_cast<char*>(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<char*>(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

View File

@ -117,14 +117,4 @@ constexpr size_t sizeofObject(size_t n) {
return n * sizeof(VariantSlot); 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 ARDUINOJSON_END_PRIVATE_NAMESPACE