• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bblanchon / ArduinoJson / 5624229712

pending completion
5624229712

push

github

bblanchon
Preallocate pool list

22 of 22 new or added lines in 1 file covered. (100.0%)

3439 of 3455 relevant lines covered (99.54%)

8768.56 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.18
/src/ArduinoJson/Memory/VariantPoolList.hpp
1
// ArduinoJson - https://arduinojson.org
2
// Copyright © 2014-2023, Benoit BLANCHON
3
// MIT License
4

5
#pragma once
6

7
#include <ArduinoJson/Memory/VariantPool.hpp>
8
#include <ArduinoJson/Polyfills/assert.hpp>
9

10
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
11

12
using PoolCount = SlotId;
13

14
class VariantPoolList {
15
 public:
16
  VariantPoolList() = default;
1,966✔
17

18
  ~VariantPoolList() {
1,966✔
19
    ARDUINOJSON_ASSERT(count_ == 0);
20
  }
1,966✔
21

22
  VariantPoolList& operator=(VariantPoolList&& src) {
7✔
23
    ARDUINOJSON_ASSERT(count_ == 0);
24
    if (src.pools_ == src.preallocatedPools_) {
7✔
25
      memcpy(preallocatedPools_, src.preallocatedPools_,
7✔
26
             sizeof(preallocatedPools_));
27
      pools_ = preallocatedPools_;
7✔
28
    } else {
29
      pools_ = src.pools_;
×
30
      src.pools_ = nullptr;
×
31
    }
32
    count_ = src.count_;
7✔
33
    capacity_ = src.capacity_;
7✔
34
    src.count_ = 0;
7✔
35
    src.capacity_ = 0;
7✔
36
    return *this;
7✔
37
  }
38

39
  SlotWithId allocSlot(Allocator* allocator) {
71,439✔
40
    // try to allocate from free list
41
    if (freeList_ != NULL_SLOT) {
71,439✔
42
      return allocFromFreeList();
131✔
43
    }
44

45
    // try to allocate from last pool (other pools are full)
46
    if (count_) {
71,308✔
47
      auto slot = allocFromLastPool();
70,204✔
48
      if (slot)
70,204✔
49
        return slot;
69,657✔
50
    }
51

52
    // create a new pool and try again
53
    auto pool = addPool(allocator);
1,651✔
54
    if (!pool)
1,651✔
55
      return {};
10✔
56

57
    return allocFromLastPool();
1,641✔
58
  }
59

60
  void freeSlot(SlotWithId slot);
61

62
  VariantSlot* getSlot(SlotId id) const {
351,818✔
63
    if (id == NULL_SLOT)
351,818✔
64
      return nullptr;
5,163✔
65
    auto poolIndex = SlotId(id / ARDUINOJSON_POOL_CAPACITY);
346,655✔
66
    auto indexInPool = SlotId(id % ARDUINOJSON_POOL_CAPACITY);
346,655✔
67
    ARDUINOJSON_ASSERT(poolIndex < count_);
68
    return pools_[poolIndex].getSlot(indexInPool);
346,655✔
69
  }
70

71
  void clear(Allocator* allocator) {
3,710✔
72
    for (PoolCount i = 0; i < count_; i++)
5,351✔
73
      pools_[i].destroy(allocator);
1,641✔
74
    count_ = 0;
3,710✔
75
    if (pools_ != preallocatedPools_) {
3,710✔
76
      allocator->deallocate(pools_);
3✔
77
      pools_ = preallocatedPools_;
3✔
78
      capacity_ = ARDUINOJSON_INITIAL_POOL_COUNT;
3✔
79
    }
80
  }
3,710✔
81

82
  SlotCount usage() const {
290✔
83
    SlotCount total = 0;
290✔
84
    for (PoolCount i = 0; i < count_; i++)
478✔
85
      total = SlotCount(total + pools_[i].usage());
188✔
86
    return total;
290✔
87
  }
88

89
  void shrinkToFit(Allocator* allocator) {
17✔
90
    if (count_ > 0)
17✔
91
      pools_[count_ - 1].shrinkToFit(allocator);
10✔
92
    if (pools_ != preallocatedPools_ && count_ != capacity_) {
17✔
93
      pools_ = static_cast<VariantPool*>(
1✔
94
          allocator->reallocate(pools_, count_ * sizeof(VariantPool)));
1✔
95
      ARDUINOJSON_ASSERT(pools_ != nullptr);  // realloc to smaller can't fail
96
      capacity_ = count_;
1✔
97
    }
98
  }
17✔
99

100
 private:
101
  SlotWithId allocFromFreeList();
102

103
  SlotWithId allocFromLastPool() {
71,845✔
104
    ARDUINOJSON_ASSERT(count_ > 0);
105
    auto poolIndex = SlotId(count_ - 1);
71,845✔
106
    auto slot = pools_[poolIndex].allocSlot();
71,845✔
107
    if (!slot)
71,845✔
108
      return {};
571✔
109
    return {slot, SlotId(poolIndex * ARDUINOJSON_POOL_CAPACITY + slot.id())};
71,274✔
110
  }
111

112
  VariantPool* addPool(Allocator* allocator) {
1,651✔
113
    if (count_ == capacity_ && !increaseCapacity(allocator))
1,651✔
114
      return nullptr;
10✔
115
    auto pool = &pools_[count_++];
1,641✔
116
    SlotCount poolCapacity = ARDUINOJSON_POOL_CAPACITY;
1,641✔
117
    if (count_ == maxPools)  // last pool is smaller because of NULL_SLOT
1,641✔
118
      poolCapacity--;
1✔
119
    pool->create(poolCapacity, allocator);
1,641✔
120
    return pool;
1,641✔
121
  }
122

123
  bool increaseCapacity(Allocator* allocator) {
20✔
124
    if (capacity_ == maxPools)
20✔
125
      return false;
10✔
126
    void* newPools;
127
    auto newCapacity = PoolCount(capacity_ * 2);
10✔
128

129
    if (pools_ == preallocatedPools_) {
10✔
130
      newPools = allocator->allocate(newCapacity * sizeof(VariantPool));
3✔
131
      if (!newPools)
3✔
132
        return false;
×
133
      memcpy(newPools, preallocatedPools_, sizeof(preallocatedPools_));
3✔
134
    } else {
135
      newPools =
136
          allocator->reallocate(pools_, newCapacity * sizeof(VariantPool));
7✔
137
      if (!newPools)
7✔
138
        return false;
×
139
    }
140

141
    pools_ = static_cast<VariantPool*>(newPools);
10✔
142
    capacity_ = newCapacity;
10✔
143
    return true;
10✔
144
  }
145

146
  VariantPool preallocatedPools_[ARDUINOJSON_INITIAL_POOL_COUNT];
147
  VariantPool* pools_ = preallocatedPools_;
148
  PoolCount count_ = 0;
149
  PoolCount capacity_ = ARDUINOJSON_INITIAL_POOL_COUNT;
150
  SlotId freeList_ = NULL_SLOT;
151

152
 public:
153
  static const PoolCount maxPools =
154
      PoolCount(NULL_SLOT / ARDUINOJSON_POOL_CAPACITY + 1);
155
};
156

157
ARDUINOJSON_END_PRIVATE_NAMESPACE
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc