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