Add abstract Allocator class

This commit is contained in:
Benoit Blanchon
2023-03-20 14:47:27 +01:00
parent 17a482a9b1
commit 24aaab6e3e
6 changed files with 127 additions and 77 deletions
+21 -18
View File
@@ -5,58 +5,60 @@
#pragma once
#include <ArduinoJson/Document/JsonDocument.hpp>
#include <ArduinoJson/Memory/Allocator.hpp>
#include <stdlib.h> // malloc, free
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
// Helper to implement the "base-from-member" idiom
// (we need to store the allocator before constructing JsonDocument)
template <typename TAllocator>
class AllocatorOwner {
public:
AllocatorOwner() {}
AllocatorOwner(TAllocator a) : _allocator(a) {}
AllocatorOwner(Allocator* allocator) : _allocator(allocator) {}
void* allocate(size_t size) {
return _allocator.allocate(size);
return _allocator->allocate(size);
}
void deallocate(void* ptr) {
if (ptr)
_allocator.deallocate(ptr);
_allocator->deallocate(ptr);
}
void* reallocate(void* ptr, size_t new_size) {
return _allocator.reallocate(ptr, new_size);
return _allocator->reallocate(ptr, new_size);
}
TAllocator& allocator() {
Allocator* allocator() {
return _allocator;
}
private:
TAllocator _allocator;
Allocator* _allocator;
};
// A JsonDocument that uses the provided allocator to allocate its memory pool.
// https://arduinojson.org/v6/api/basicjsondocument/
template <typename TAllocator>
class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
class BasicJsonDocument : AllocatorOwner, public JsonDocument {
public:
explicit BasicJsonDocument(size_t capa, TAllocator alloc = TAllocator())
: AllocatorOwner<TAllocator>(alloc), JsonDocument(allocPool(capa)) {}
explicit BasicJsonDocument(
size_t capa, Allocator* alloc = detail::DefaultAllocator::instance())
: AllocatorOwner(alloc), JsonDocument(allocPool(capa)) {}
// Copy-constructor
BasicJsonDocument(const BasicJsonDocument& src)
: AllocatorOwner<TAllocator>(src), JsonDocument() {
: AllocatorOwner(src), JsonDocument() {
copyAssignFrom(src);
}
// Move-constructor
BasicJsonDocument(BasicJsonDocument&& src) : AllocatorOwner<TAllocator>(src) {
BasicJsonDocument(BasicJsonDocument&& src) : AllocatorOwner(src) {
moveAssignFrom(src);
}
BasicJsonDocument(const JsonDocument& src) {
BasicJsonDocument(const JsonDocument& src)
: AllocatorOwner(detail::DefaultAllocator::instance()) {
copyAssignFrom(src);
}
@@ -70,13 +72,14 @@ class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
detail::is_same<T, JsonArrayConst>::value ||
detail::is_same<T, JsonObject>::value ||
detail::is_same<T, JsonObjectConst>::value>::type* = 0)
: JsonDocument(allocPool(src.memoryUsage())) {
: BasicJsonDocument(src.memoryUsage()) {
set(src);
}
// disambiguate
BasicJsonDocument(JsonVariant src)
: JsonDocument(allocPool(src.memoryUsage())) {
: AllocatorOwner(detail::DefaultAllocator::instance()),
JsonDocument(allocPool(src.memoryUsage())) {
set(src);
}
@@ -132,7 +135,7 @@ class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
return true;
}
using AllocatorOwner<TAllocator>::allocator;
using AllocatorOwner::allocator;
private:
detail::MemoryPool allocPool(size_t requiredSize) {
@@ -6,27 +6,10 @@
#include <ArduinoJson/Document/BasicJsonDocument.hpp>
#include <stdlib.h> // malloc, free
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
// The allocator of DynamicJsonDocument.
struct DefaultAllocator {
void* allocate(size_t size) {
return malloc(size);
}
void deallocate(void* ptr) {
free(ptr);
}
void* reallocate(void* ptr, size_t new_size) {
return realloc(ptr, new_size);
}
};
// A JsonDocument with a memory pool in the heap.
// https://arduinojson.org/v6/api/dynamicjsondocument/
typedef BasicJsonDocument<DefaultAllocator> DynamicJsonDocument;
typedef BasicJsonDocument DynamicJsonDocument;
ARDUINOJSON_END_PUBLIC_NAMESPACE
+49
View File
@@ -0,0 +1,49 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Namespace.hpp>
#include <stdlib.h> // malloc, free
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
class Allocator {
public:
virtual void* allocate(size_t size) = 0;
virtual void deallocate(void* ptr) = 0;
virtual void* reallocate(void* ptr, size_t new_size) = 0;
protected:
~Allocator() = default;
};
namespace detail {
class DefaultAllocator : public Allocator {
public:
void* allocate(size_t size) override {
return malloc(size);
}
void deallocate(void* ptr) override {
free(ptr);
}
void* reallocate(void* ptr, size_t new_size) override {
return realloc(ptr, new_size);
}
static Allocator* instance() {
static DefaultAllocator allocator;
return &allocator;
}
private:
DefaultAllocator() = default;
~DefaultAllocator() = default;
};
} // namespace detail
ARDUINOJSON_END_PUBLIC_NAMESPACE