heap_based_pool_allocator.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
5 #ifndef UAVCAN_HELPERS_HEAP_BASED_POOL_ALLOCATOR_HPP_INCLUDED
6 #define UAVCAN_HELPERS_HEAP_BASED_POOL_ALLOCATOR_HPP_INCLUDED
7 
8 #include <cstdlib>
10 #include <uavcan/debug.hpp>
12 
13 namespace uavcan
14 {
38 template <std::size_t BlockSize,
39  typename RaiiSynchronizer = char>
42 {
43  union Node
44  {
46  private:
47  uint8_t data[BlockSize];
48  long double _aligner1;
49  long long _aligner2;
50  };
51 
54 
57 
59 
60 public:
70  HeapBasedPoolAllocator(uint16_t block_capacity_soft_limit,
71  uint16_t block_capacity_hard_limit = 0) :
72  capacity_soft_limit_(block_capacity_soft_limit),
73  capacity_hard_limit_((block_capacity_hard_limit > 0) ? block_capacity_hard_limit :
74  static_cast<uint16_t>(min(static_cast<uint32_t>(block_capacity_soft_limit) * 2U,
75  static_cast<uint32_t>(NumericTraits<uint16_t>::max())))),
76  num_reserved_blocks_(0),
77  num_allocated_blocks_(0),
78  reserve_(UAVCAN_NULLPTR)
79  { }
80 
86  {
87  shrink();
88 #if UAVCAN_DEBUG
89  if (num_allocated_blocks_ > 0)
90  {
91  UAVCAN_TRACE("HeapBasedPoolAllocator", "%u BLOCKS LEAKED", num_allocated_blocks_);
92  }
93 #endif
94  }
95 
100  virtual void* allocate(std::size_t size)
101  {
102  if (size > BlockSize)
103  {
104  return UAVCAN_NULLPTR;
105  }
106 
107  {
108  RaiiSynchronizer lock;
109  (void)lock;
110 
111  Node* const p = reserve_;
112 
113  if (UAVCAN_LIKELY(p != UAVCAN_NULLPTR))
114  {
115  reserve_ = reserve_->next;
116  num_allocated_blocks_++;
117  return p;
118  }
119 
120  if (num_reserved_blocks_ >= capacity_hard_limit_) // Hard limit reached, no further allocations
121  {
122  return UAVCAN_NULLPTR;
123  }
124  }
125 
126  // Unlikely branch
127  void* const m = std::malloc(sizeof(Node));
128  if (m != UAVCAN_NULLPTR)
129  {
130  RaiiSynchronizer lock;
131  (void)lock;
132 
133  num_reserved_blocks_++;
134  num_allocated_blocks_++;
135  }
136  return m;
137  }
138 
143  virtual void deallocate(const void* ptr)
144  {
145  if (ptr != UAVCAN_NULLPTR)
146  {
147  RaiiSynchronizer lock;
148  (void)lock;
149 
150  Node* const node = static_cast<Node*>(const_cast<void*>(ptr));
151  node->next = reserve_;
152  reserve_ = node;
153 
154  num_allocated_blocks_--;
155  }
156  }
157 
161  virtual uint16_t getBlockCapacity() const { return capacity_soft_limit_; }
162 
166  uint16_t getBlockCapacityHardLimit() const { return capacity_hard_limit_; }
167 
172  void shrink()
173  {
174  Node* p = UAVCAN_NULLPTR;
175  for (;;)
176  {
177  {
178  RaiiSynchronizer lock;
179  (void)lock;
180  // Removing from reserve and updating the counter.
181  p = reserve_;
182  if (p != UAVCAN_NULLPTR)
183  {
184  reserve_ = reserve_->next;
185  num_reserved_blocks_--;
186  }
187  else
188  {
189  break;
190  }
191  }
192  // Then freeing, having left the critical section.
193  std::free(p);
194  }
195  }
196 
201  {
202  RaiiSynchronizer lock;
203  (void)lock;
204  return num_allocated_blocks_;
205  }
206 
211  {
212  RaiiSynchronizer lock;
213  (void)lock;
214  return num_reserved_blocks_;
215  }
216 };
217 
218 }
219 
220 #endif
std::uint8_t uint8_t
Definition: std.hpp:24
struct UAVCAN_EXPORT NumericTraits
Definition: templates.hpp:342
unsigned long size_t
virtual void deallocate(const void *ptr)
virtual void * allocate(std::size_t size)
UAVCAN_EXPORT const T & max(const T &a, const T &b)
Definition: templates.hpp:291
HeapBasedPoolAllocator(uint16_t block_capacity_soft_limit, uint16_t block_capacity_hard_limit=0)
std::uint32_t uint32_t
Definition: std.hpp:26
UAVCAN_EXPORT const T & min(const T &a, const T &b)
Definition: templates.hpp:281
std::uint16_t uint16_t
Definition: std.hpp:25


uavcan_communicator
Author(s):
autogenerated on Wed Jan 11 2023 03:59:39