openMSX
ObjectPool_test.cc
Go to the documentation of this file.
1#include "catch.hpp"
2
3#include "ObjectPool.hh"
4#include "xrange.hh"
5#include <vector>
6
7
8struct Tracked
9{
10 static inline std::vector<int> constructed;
11 static inline std::vector<int> destructed;
12
13 explicit Tracked(int i_) : i(i_) {
14 constructed.push_back(i);
15 }
17 destructed.push_back(i);
18 }
19 int i;
20};
21
22TEST_CASE("ObjectPool")
23{
24 REQUIRE(Tracked::constructed.empty());
25 REQUIRE(Tracked::destructed.empty());
26
27 {
29 CHECK(pool.capacity() == 0); // empty pool does no memory allocation
30
31 // insert '10'
32 auto [idx1, ptr1] = pool.emplace(10);
33 CHECK(ptr1->i == 10);
34 CHECK(&pool[idx1] == ptr1);
35 CHECK(Tracked::constructed == std::vector{10});
36 CHECK(Tracked::destructed == std::vector<int>{});
37 CHECK(pool.capacity() == 256); // allocates in chunks of 256
38
39 // insert '20'
40 auto [idx2, ptr2] = pool.emplace(20);
41 CHECK(ptr1->i == 10);
42 CHECK(ptr2->i == 20);
43 CHECK(&pool[idx1] == ptr1);
44 CHECK(&pool[idx2] == ptr2);
45 CHECK(Tracked::constructed == std::vector{10, 20});
46 CHECK(Tracked::destructed == std::vector<int>{});
47
48 // insert '30'
49 auto [idx3, ptr3] = pool.emplace(30);
50 CHECK(ptr1->i == 10);
51 CHECK(ptr2->i == 20);
52 CHECK(ptr3->i == 30);
53 CHECK(&pool[idx1] == ptr1);
54 CHECK(&pool[idx2] == ptr2);
55 CHECK(&pool[idx3] == ptr3);
56 CHECK(Tracked::constructed == std::vector{10, 20, 30});
57 CHECK(Tracked::destructed == std::vector<int>{});
58
59 // remove '20'
60 pool.remove(idx2);
61 CHECK(ptr1->i == 10);
62 CHECK(ptr3->i == 30);
63 CHECK(&pool[idx1] == ptr1);
64 CHECK(&pool[idx3] == ptr3);
65 CHECK(Tracked::constructed == std::vector{10, 20, 30});
66 CHECK(Tracked::destructed == std::vector{20});
67
68 // insert '40'
69 auto [idx4, ptr4] = pool.emplace(40);
70 CHECK(idx4 == idx2); // recycled
71 CHECK(ptr1->i == 10);
72 CHECK(ptr3->i == 30);
73 CHECK(ptr4->i == 40);
74 CHECK(&pool[idx1] == ptr1);
75 CHECK(&pool[idx3] == ptr3);
76 CHECK(&pool[idx4] == ptr4);
77 CHECK(Tracked::constructed == std::vector{10, 20, 30, 40});
78 CHECK(Tracked::destructed == std::vector{20});
79 CHECK(pool.capacity() == 256);
80
81 // insert a lot more (force allocating more memory in the pool)
82 for (auto i : xrange(1000)) {
83 auto val = 1000 + i;
84 auto [idx, ptr] = pool.emplace(val);
85 CHECK(ptr->i == val);
86 CHECK(&pool[idx] == ptr);
87 }
88 CHECK(Tracked::constructed.size() == 1004);
89 CHECK(Tracked::destructed == std::vector{20});
90 CHECK(pool.capacity() == 1024);
91 }
92
93 // When 'pool' goes out of scope it does _not_ destruct the elements it
94 // still contained. (But it does free the memory it used to store those
95 // elements.)
96 CHECK(Tracked::constructed.size() == 1004);
97 CHECK(Tracked::destructed == std::vector{20});
98}
99
100
101// To (manually) inspect quality of generated code
102#if 0
103
104auto inspect_operator(ObjectPool<int>& pool, unsigned idx)
105{
106 return pool[idx];
107}
108
109auto inspect_emplace(ObjectPool<int>& pool, int val)
110{
111 return pool.emplace(val);
112}
113
114void inspect_remove(ObjectPool<int>& pool, unsigned idx)
115{
116 return pool.remove(idx);
117}
118
119#endif
TEST_CASE("ObjectPool")
Index capacity() const
void remove(Index idx)
Definition ObjectPool.hh:96
EmplaceResult emplace(Args &&...args)
Definition ObjectPool.hh:76
CHECK(m3==m3)
static std::vector< int > constructed
Tracked(int i_)
static std::vector< int > destructed
constexpr auto xrange(T e)
Definition xrange.hh:132