From 8147625921af9effa366f305a8fc60e75696bd42 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Fri, 16 Jun 2023 16:09:40 +0200 Subject: [PATCH] ResourceManager: replace `allocFromPool()` with `allocVariant()` --- extras/tests/ResourceManager/allocVariant.cpp | 18 +++++++++--------- extras/tests/ResourceManager/clear.cpp | 2 +- extras/tests/ResourceManager/size.cpp | 4 ++-- .../Collection/CollectionFunctions.hpp | 4 ++-- src/ArduinoJson/Json/JsonDeserializer.hpp | 2 +- src/ArduinoJson/Memory/ResourceManager.hpp | 16 +++------------- .../MsgPack/MsgPackDeserializer.hpp | 2 +- src/ArduinoJson/Variant/VariantData.hpp | 2 +- src/ArduinoJson/Variant/VariantSlot.hpp | 19 ++++++++++++++----- 9 files changed, 34 insertions(+), 35 deletions(-) diff --git a/extras/tests/ResourceManager/allocVariant.cpp b/extras/tests/ResourceManager/allocVariant.cpp index 4cb88d6a..8d906a9f 100644 --- a/extras/tests/ResourceManager/allocVariant.cpp +++ b/extras/tests/ResourceManager/allocVariant.cpp @@ -10,13 +10,13 @@ using namespace ArduinoJson::detail; -TEST_CASE("new (resources) VariantSlot()") { +TEST_CASE("ResourceManager::allocVariant()") { SECTION("Returns different pointer") { ResourceManager resources(4096); - VariantSlot* s1 = new (&resources) VariantSlot(); + VariantSlot* s1 = resources.allocVariant(); REQUIRE(s1 != 0); - VariantSlot* s2 = new (&resources) VariantSlot(); + VariantSlot* s2 = resources.allocVariant(); REQUIRE(s2 != 0); REQUIRE(s1 != s2); @@ -25,27 +25,27 @@ TEST_CASE("new (resources) VariantSlot()") { SECTION("Returns aligned pointers") { ResourceManager resources(4096); - REQUIRE(isAligned(new (&resources) VariantSlot())); - REQUIRE(isAligned(new (&resources) VariantSlot())); + REQUIRE(isAligned(resources.allocVariant())); + REQUIRE(isAligned(resources.allocVariant())); } SECTION("Returns zero if capacity is 0") { ResourceManager resources(0); - REQUIRE(new (&resources) VariantSlot() == 0); + REQUIRE(resources.allocVariant() == 0); } SECTION("Returns zero if buffer is null") { ResourceManager resources(4096, FailingAllocator::instance()); - REQUIRE(new (&resources) VariantSlot() == 0); + REQUIRE(resources.allocVariant() == 0); } SECTION("Returns zero if capacity is insufficient") { ResourceManager resources(sizeof(VariantSlot)); - new (&resources) VariantSlot(); + resources.allocVariant(); - REQUIRE(new (&resources) VariantSlot() == 0); + REQUIRE(resources.allocVariant() == 0); } } diff --git a/extras/tests/ResourceManager/clear.cpp b/extras/tests/ResourceManager/clear.cpp index 8c7a1200..6060926c 100644 --- a/extras/tests/ResourceManager/clear.cpp +++ b/extras/tests/ResourceManager/clear.cpp @@ -15,7 +15,7 @@ TEST_CASE("ResourceManager::clear()") { ResourceManager resources(poolCapacity); SECTION("Discards allocated variants") { - new (&resources) VariantSlot(); + resources.allocVariant(); resources.clear(); REQUIRE(resources.size() == 0); diff --git a/extras/tests/ResourceManager/size.cpp b/extras/tests/ResourceManager/size.cpp index da3a9903..7509e325 100644 --- a/extras/tests/ResourceManager/size.cpp +++ b/extras/tests/ResourceManager/size.cpp @@ -25,10 +25,10 @@ TEST_CASE("ResourceManager::size()") { const size_t variantCount = resources.capacity() / sizeof(VariantSlot); for (size_t i = 0; i < variantCount; i++) - new (&resources) VariantSlot(); + resources.allocVariant(); size_t size = resources.size(); - new (&resources) VariantSlot(); + resources.allocVariant(); REQUIRE(size == resources.size()); } diff --git a/src/ArduinoJson/Collection/CollectionFunctions.hpp b/src/ArduinoJson/Collection/CollectionFunctions.hpp index d23f3f49..08dcad65 100644 --- a/src/ArduinoJson/Collection/CollectionFunctions.hpp +++ b/src/ArduinoJson/Collection/CollectionFunctions.hpp @@ -12,7 +12,7 @@ inline VariantData* collectionAddElement(CollectionData* array, ResourceManager* resources) { if (!array) return nullptr; - auto slot = new (resources) VariantSlot(); + auto slot = resources->allocVariant(); if (!slot) return nullptr; array->add(slot); @@ -24,7 +24,7 @@ inline VariantData* collectionAddMember(CollectionData* obj, TAdaptedString key, ResourceManager* resources) { ARDUINOJSON_ASSERT(!key.isNull()); ARDUINOJSON_ASSERT(obj != nullptr); - auto slot = new (resources) VariantSlot(); + auto slot = resources->allocVariant(); if (!slot) return nullptr; if (key.isLinked()) diff --git a/src/ArduinoJson/Json/JsonDeserializer.hpp b/src/ArduinoJson/Json/JsonDeserializer.hpp index d19d86a9..a585564f 100644 --- a/src/ArduinoJson/Json/JsonDeserializer.hpp +++ b/src/ArduinoJson/Json/JsonDeserializer.hpp @@ -279,7 +279,7 @@ class JsonDeserializer { auto savedKey = stringBuilder_.save(); // Allocate slot in object - slot = new (resources_) VariantSlot(); + slot = resources_->allocVariant(); if (!slot) return DeserializationError::NoMemory; diff --git a/src/ArduinoJson/Memory/ResourceManager.hpp b/src/ArduinoJson/Memory/ResourceManager.hpp index 165473fa..55f0fc2f 100644 --- a/src/ArduinoJson/Memory/ResourceManager.hpp +++ b/src/ArduinoJson/Memory/ResourceManager.hpp @@ -12,6 +12,8 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE +class VariantSlot; + class ResourceManager { public: ResourceManager(size_t capa, @@ -71,15 +73,7 @@ class ResourceManager { return overflowed_; } - void* allocFromPool(size_t bytes) { - if (!canAlloc(bytes)) { - overflowed_ = true; - return 0; - } - auto p = pool_ + poolUsage_; - poolUsage_ += bytes; - return p; - } + VariantSlot* allocVariant(); template StringNode* saveString(TAdaptedString str) { @@ -171,10 +165,6 @@ class ResourceManager { deallocAllStrings(); } - bool canAlloc(size_t bytes) const { - return poolUsage_ + bytes <= poolCapacity_; - } - // Workaround for missing placement new void* operator new(size_t, void* p) { return p; diff --git a/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp b/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp index 92e2707f..7fe8e602 100644 --- a/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp +++ b/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp @@ -495,7 +495,7 @@ class MsgPackDeserializer { // Save key in memory pool. auto savedKey = stringBuilder_.save(); - VariantSlot* slot = new (resources_) VariantSlot(); + VariantSlot* slot = resources_->allocVariant(); if (!slot) return DeserializationError::NoMemory; diff --git a/src/ArduinoJson/Variant/VariantData.hpp b/src/ArduinoJson/Variant/VariantData.hpp index 39b9fa1d..dcd437fd 100644 --- a/src/ArduinoJson/Variant/VariantData.hpp +++ b/src/ArduinoJson/Variant/VariantData.hpp @@ -234,7 +234,7 @@ class VariantData { if (!slot) index++; while (index > 0) { - slot = new (resources) VariantSlot(); + slot = resources->allocVariant(); if (!slot) return nullptr; array->add(slot); diff --git a/src/ArduinoJson/Variant/VariantSlot.hpp b/src/ArduinoJson/Variant/VariantSlot.hpp index 44f76eeb..155f6e3e 100644 --- a/src/ArduinoJson/Variant/VariantSlot.hpp +++ b/src/ArduinoJson/Variant/VariantSlot.hpp @@ -26,13 +26,12 @@ class VariantSlot { const char* key_; public: - static void* operator new(size_t size, ResourceManager* resources) noexcept { - return resources->allocFromPool(size); + // Placement new + static void* operator new(size_t, void* p) noexcept { + return p; } - static void operator delete(void*, ResourceManager*) noexcept { - // we cannot release memory from the pool - } + static void operator delete(void*, void*) noexcept {} VariantSlot() : flags_(0), next_(0), key_(0) {} @@ -118,4 +117,14 @@ 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