heap_based_pool_allocator.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
5 #include <gtest/gtest.h>
7 #ifdef __linux__
8 #include <malloc.h>
9 
10 #else
11 #include <stdlib.h>
12 #endif
13 
14 TEST(HeapBasedPoolAllocator, Basic)
15 {
16 #ifdef __linux__
17  std::cout << ">>> HEAP BEFORE:" << std::endl;
18  malloc_stats();
19 #endif
20 
22 
23  ASSERT_EQ(0, al.getNumReservedBlocks());
24  ASSERT_EQ(0, al.getNumAllocatedBlocks());
25 
26  ASSERT_EQ(0xEEEE, al.getBlockCapacity());
27  ASSERT_EQ(0xFFFF, al.getBlockCapacityHardLimit());
28 
29  void* a = al.allocate(10);
30  void* b = al.allocate(10);
31  void* c = al.allocate(10);
32  void* d = al.allocate(10);
33 
34  ASSERT_EQ(4, al.getNumReservedBlocks());
35  ASSERT_EQ(4, al.getNumAllocatedBlocks());
36 
37  al.deallocate(a);
38  ASSERT_EQ(4, al.getNumReservedBlocks());
39  ASSERT_EQ(3, al.getNumAllocatedBlocks());
40 
41  al.deallocate(b);
42  ASSERT_EQ(4, al.getNumReservedBlocks());
43  ASSERT_EQ(2, al.getNumAllocatedBlocks());
44 
45  al.deallocate(c);
46  ASSERT_EQ(4, al.getNumReservedBlocks());
47  ASSERT_EQ(1, al.getNumAllocatedBlocks());
48 
49  a = al.allocate(10);
50  ASSERT_EQ(4, al.getNumReservedBlocks());
51  ASSERT_EQ(2, al.getNumAllocatedBlocks());
52  ASSERT_EQ(c, a);
53 
54  al.deallocate(a);
55  ASSERT_EQ(4, al.getNumReservedBlocks());
56  ASSERT_EQ(1, al.getNumAllocatedBlocks());
57 
58  al.shrink();
59  ASSERT_EQ(1, al.getNumReservedBlocks());
60  ASSERT_EQ(1, al.getNumAllocatedBlocks());
61 
62  al.deallocate(d);
63  ASSERT_EQ(1, al.getNumReservedBlocks());
64  ASSERT_EQ(0, al.getNumAllocatedBlocks());
65 
66  al.shrink();
67  ASSERT_EQ(0, al.getNumReservedBlocks());
68  ASSERT_EQ(0, al.getNumAllocatedBlocks());
69 
70 #ifdef __linux__
71  std::cout << ">>> HEAP AFTER:" << std::endl;
72  malloc_stats();
73 #endif
74 }
75 
76 
77 TEST(HeapBasedPoolAllocator, Limits)
78 {
80 
81  ASSERT_EQ(2, al.getBlockCapacity());
82  ASSERT_EQ(4, al.getBlockCapacityHardLimit());
83 
84  ASSERT_EQ(0, al.getNumReservedBlocks());
85  ASSERT_EQ(0, al.getNumAllocatedBlocks());
86 
87  void* a = al.allocate(10);
88  void* b = al.allocate(10);
89  void* c = al.allocate(10);
90  void* d = al.allocate(10);
91 
92  ASSERT_TRUE(a);
93  ASSERT_TRUE(b);
94  ASSERT_TRUE(c);
95  ASSERT_TRUE(d);
96 
97  ASSERT_FALSE(al.allocate(10));
98 
99  ASSERT_EQ(4, al.getNumReservedBlocks());
100  ASSERT_EQ(4, al.getNumAllocatedBlocks());
101 
102  al.deallocate(a);
103  al.deallocate(b);
104  al.deallocate(c);
105  al.deallocate(d);
106 
107  ASSERT_EQ(4, al.getNumReservedBlocks());
108  ASSERT_EQ(0, al.getNumAllocatedBlocks());
109 }
110 
111 #if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
112 
113 #include <thread>
114 #include <mutex>
115 
117 {
118  static std::mutex mutex;
119  std::lock_guard<std::mutex> guard{mutex};
120 };
121 
122 std::mutex RaiiSynchronizer::mutex;
123 
124 TEST(HeapBasedPoolAllocator, Concurrency)
125 {
126 #ifdef __linux__
127  std::cout << ">>> HEAP BEFORE:" << std::endl;
128  malloc_stats();
129 
130 #endif
132 
133  ASSERT_EQ(1000, al.getBlockCapacity());
134  ASSERT_EQ(2000, al.getBlockCapacityHardLimit());
135 
136  volatile bool terminate = false;
137 
138  /*
139  * Starting the testing threads
140  */
141  std::thread threads[3];
142 
143  for (auto& x : threads)
144  {
145  x = std::thread([&al, &terminate]()
146  {
147  while (!terminate)
148  {
149  auto a = al.allocate(1);
150  auto b = al.allocate(1);
151  auto c = al.allocate(1);
152  al.deallocate(al.allocate(1));
153  al.deallocate(a);
154  al.deallocate(b);
155  al.deallocate(c);
156  }
157  });
158  }
159 
160  /*
161  * Running the threads for some time, then terminating
162  */
163  std::this_thread::sleep_for(std::chrono::seconds(1));
164 
165  terminate = true;
166  std::cout << "Terminating workers..." << std::endl;
167 
168  for (auto& x : threads)
169  {
170  x.join();
171  }
172  std::cout << "All workers joined" << std::endl;
173 
174  /*
175  * Now, there must not be any leaked memory, because the worker threads deallocate everything before completion.
176  */
177  std::cout << "Allocated: " << al.getNumAllocatedBlocks() << std::endl;
178  std::cout << "Reserved: " << al.getNumReservedBlocks() << std::endl;
179 
180 #ifdef __linux__
181  std::cout << ">>> HEAP BEFORE SHRINK:" << std::endl;
182  malloc_stats();
183 
184 #endif
185  al.shrink();
186 
187 #ifdef __linux__
188  std::cout << ">>> HEAP AFTER SHRINK:" << std::endl;
189  malloc_stats();
190 #endif
191 }
192 
193 #endif
RaiiSynchronizer::guard
std::lock_guard< std::mutex > guard
Definition: heap_based_pool_allocator.cpp:119
uavcan::HeapBasedPoolAllocator::getNumReservedBlocks
uint16_t getNumReservedBlocks() const
Definition: heap_based_pool_allocator.hpp:210
RaiiSynchronizer::mutex
static std::mutex mutex
Definition: heap_based_pool_allocator.cpp:118
uavcan::HeapBasedPoolAllocator::allocate
virtual void * allocate(std::size_t size)
Definition: heap_based_pool_allocator.hpp:100
uavcan::HeapBasedPoolAllocator::deallocate
virtual void deallocate(const void *ptr)
Definition: heap_based_pool_allocator.hpp:143
heap_based_pool_allocator.hpp
d
d
uavcan::HeapBasedPoolAllocator::getBlockCapacity
virtual uint16_t getBlockCapacity() const
Definition: heap_based_pool_allocator.hpp:161
uavcan::HeapBasedPoolAllocator::getBlockCapacityHardLimit
uint16_t getBlockCapacityHardLimit() const
Definition: heap_based_pool_allocator.hpp:166
uavcan::HeapBasedPoolAllocator::shrink
void shrink()
Definition: heap_based_pool_allocator.hpp:172
RaiiSynchronizer
Definition: heap_based_pool_allocator.cpp:116
uavcan::HeapBasedPoolAllocator::getNumAllocatedBlocks
uint16_t getNumAllocatedBlocks() const
Definition: heap_based_pool_allocator.hpp:200
TEST
TEST(HeapBasedPoolAllocator, Basic)
Definition: heap_based_pool_allocator.cpp:14
uavcan::HeapBasedPoolAllocator< uavcan::MemPoolBlockSize >
pyuavcan_v0.driver.timestamp_estimator.x
x
Definition: timestamp_estimator.py:221


uavcan_communicator
Author(s):
autogenerated on Fri Dec 13 2024 03:10:02