Bläddra i källkod

Extract `VariantPool` from `ResourceManager`

Benoit Blanchon 2 år sedan
förälder
incheckning
d90b36c009

+ 1 - 1
extras/tests/ResourceManager/allocVariant.cpp

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

+ 1 - 1
extras/tests/ResourceManager/clear.cpp

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

+ 1 - 1
extras/tests/ResourceManager/size.cpp

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

+ 1 - 0
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"

+ 20 - 32
src/ArduinoJson/Memory/ResourceManager.hpp

@@ -7,24 +7,27 @@
 #include <ArduinoJson/Memory/Alignment.hpp>
 #include <ArduinoJson/Memory/Allocator.hpp>
 #include <ArduinoJson/Memory/StringNode.hpp>
+#include <ArduinoJson/Memory/VariantPool.hpp>
 #include <ArduinoJson/Polyfills/assert.hpp>
+#include <ArduinoJson/Polyfills/utility.hpp>
 #include <ArduinoJson/Strings/StringAdapters.hpp>
 
 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 <typename TAdaptedString>
   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<char*>(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<char*>(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

+ 47 - 0
src/ArduinoJson/Memory/VariantPool.hpp

@@ -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

+ 61 - 0
src/ArduinoJson/Memory/VariantPoolImpl.hpp

@@ -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

+ 0 - 10
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