Reference-count shared strings

This commit is contained in:
Benoit Blanchon
2023-04-21 16:11:54 +02:00
parent b7c8e0d25c
commit 003087406c
9 changed files with 131 additions and 24 deletions
+20
View File
@@ -28,6 +28,7 @@ constexpr size_t sizeofObject(size_t n) {
struct StringNode {
struct StringNode* next;
uint16_t length;
uint16_t references;
char data[1];
};
@@ -112,6 +113,7 @@ class MemoryPool {
auto node = findString(str);
if (node) {
node->references++;
return node->data;
}
@@ -147,6 +149,7 @@ class MemoryPool {
_allocator->allocate(sizeofString(length)));
if (node) {
node->length = uint16_t(length);
node->references = 1;
} else {
_overflowed = true;
}
@@ -170,6 +173,23 @@ class MemoryPool {
_allocator->deallocate(node);
}
void dereferenceString(const char* s) {
StringNode* prev = nullptr;
for (auto node = _strings; node; node = node->next) {
if (node->data == s) {
if (--node->references == 0) {
if (prev)
prev->next = node->next;
else
_strings = node->next;
_allocator->deallocate(node);
}
return;
}
prev = node;
}
}
void clear() {
_right = _end;
_overflowed = false;
@@ -33,6 +33,8 @@ class StringCopier {
node = _pool->reallocString(_node, _size);
_pool->addStringToList(node);
_node = nullptr; // next time we need a new string
} else {
node->references++;
}
return JsonString(node->data, node->length, JsonString::Copied);
}
@@ -24,6 +24,8 @@ inline VariantData* slotData(VariantSlot* slot) {
inline void slotRelease(const VariantSlot* slot, MemoryPool* pool) {
ARDUINOJSON_ASSERT(slot != nullptr);
if (slot->ownsKey())
pool->dereferenceString(slot->key());
variantRelease(slot->data(), pool);
}
@@ -33,6 +33,10 @@ inline typename TVisitor::result_type variantAccept(const VariantData* var,
inline void variantRelease(const VariantData* var, MemoryPool* pool) {
ARDUINOJSON_ASSERT(var != nullptr);
auto s = var->getOwnedString();
if (s)
pool->dereferenceString(s);
auto c = var->asCollection();
if (c) {
for (auto slot = c->head(); slot; slot = slot->next())