1 // Copyright 2019 The Marl Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "marl_test.h"
16
17 #include "marl/memory.h"
18 #include "marl/pool.h"
19 #include "marl/waitgroup.h"
20
TEST_P(WithBoundScheduler,UnboundedPool_ConstructDestruct)21 TEST_P(WithBoundScheduler, UnboundedPool_ConstructDestruct) {
22 marl::UnboundedPool<int> pool;
23 }
24
TEST_P(WithBoundScheduler,BoundedPool_ConstructDestruct)25 TEST_P(WithBoundScheduler, BoundedPool_ConstructDestruct) {
26 marl::BoundedPool<int, 10> pool;
27 }
28
TEST_P(WithBoundScheduler,UnboundedPoolLoan_GetNull)29 TEST_P(WithBoundScheduler, UnboundedPoolLoan_GetNull) {
30 marl::UnboundedPool<int>::Loan loan;
31 ASSERT_EQ(loan.get(), nullptr);
32 }
33
TEST_P(WithBoundScheduler,BoundedPoolLoan_GetNull)34 TEST_P(WithBoundScheduler, BoundedPoolLoan_GetNull) {
35 marl::BoundedPool<int, 10>::Loan loan;
36 ASSERT_EQ(loan.get(), nullptr);
37 }
38
TEST_P(WithBoundScheduler,UnboundedPool_Borrow)39 TEST_P(WithBoundScheduler, UnboundedPool_Borrow) {
40 marl::UnboundedPool<int> pool;
41 for (int i = 0; i < 100; i++) {
42 pool.borrow();
43 }
44 }
45
TEST_P(WithBoundScheduler,UnboundedPool_ConcurrentBorrow)46 TEST_P(WithBoundScheduler, UnboundedPool_ConcurrentBorrow) {
47 marl::UnboundedPool<int> pool;
48 constexpr int iterations = 10000;
49 marl::WaitGroup wg(iterations);
50 for (int i = 0; i < iterations; i++) {
51 marl::schedule([=] {
52 pool.borrow();
53 wg.done();
54 });
55 }
56 wg.wait();
57 }
58
TEST_P(WithBoundScheduler,BoundedPool_Borrow)59 TEST_P(WithBoundScheduler, BoundedPool_Borrow) {
60 marl::BoundedPool<int, 100> pool;
61 for (int i = 0; i < 100; i++) {
62 pool.borrow();
63 }
64 }
65
TEST_P(WithBoundScheduler,BoundedPool_ConcurrentBorrow)66 TEST_P(WithBoundScheduler, BoundedPool_ConcurrentBorrow) {
67 marl::BoundedPool<int, 10> pool;
68 constexpr int iterations = 10000;
69 marl::WaitGroup wg(iterations);
70 for (int i = 0; i < iterations; i++) {
71 marl::schedule([=] {
72 pool.borrow();
73 wg.done();
74 });
75 }
76 wg.wait();
77 }
78
79 struct CtorDtorCounter {
CtorDtorCounterCtorDtorCounter80 CtorDtorCounter() { ctor_count++; }
~CtorDtorCounterCtorDtorCounter81 ~CtorDtorCounter() { dtor_count++; }
resetCtorDtorCounter82 static void reset() {
83 ctor_count = 0;
84 dtor_count = 0;
85 }
86 static int ctor_count;
87 static int dtor_count;
88 };
89
90 int CtorDtorCounter::ctor_count = -1;
91 int CtorDtorCounter::dtor_count = -1;
92
TEST_P(WithBoundScheduler,UnboundedPool_PolicyReconstruct)93 TEST_P(WithBoundScheduler, UnboundedPool_PolicyReconstruct) {
94 CtorDtorCounter::reset();
95 marl::UnboundedPool<CtorDtorCounter, marl::PoolPolicy::Reconstruct> pool;
96 ASSERT_EQ(CtorDtorCounter::ctor_count, 0);
97 ASSERT_EQ(CtorDtorCounter::dtor_count, 0);
98 {
99 auto loan = pool.borrow();
100 ASSERT_EQ(CtorDtorCounter::ctor_count, 1);
101 ASSERT_EQ(CtorDtorCounter::dtor_count, 0);
102 }
103 ASSERT_EQ(CtorDtorCounter::ctor_count, 1);
104 ASSERT_EQ(CtorDtorCounter::dtor_count, 1);
105 {
106 auto loan = pool.borrow();
107 ASSERT_EQ(CtorDtorCounter::ctor_count, 2);
108 ASSERT_EQ(CtorDtorCounter::dtor_count, 1);
109 }
110 ASSERT_EQ(CtorDtorCounter::ctor_count, 2);
111 ASSERT_EQ(CtorDtorCounter::dtor_count, 2);
112 }
113
TEST_P(WithBoundScheduler,BoundedPool_PolicyReconstruct)114 TEST_P(WithBoundScheduler, BoundedPool_PolicyReconstruct) {
115 CtorDtorCounter::reset();
116 marl::BoundedPool<CtorDtorCounter, 10, marl::PoolPolicy::Reconstruct> pool;
117 ASSERT_EQ(CtorDtorCounter::ctor_count, 0);
118 ASSERT_EQ(CtorDtorCounter::dtor_count, 0);
119 {
120 auto loan = pool.borrow();
121 ASSERT_EQ(CtorDtorCounter::ctor_count, 1);
122 ASSERT_EQ(CtorDtorCounter::dtor_count, 0);
123 }
124 ASSERT_EQ(CtorDtorCounter::ctor_count, 1);
125 ASSERT_EQ(CtorDtorCounter::dtor_count, 1);
126 {
127 auto loan = pool.borrow();
128 ASSERT_EQ(CtorDtorCounter::ctor_count, 2);
129 ASSERT_EQ(CtorDtorCounter::dtor_count, 1);
130 }
131 ASSERT_EQ(CtorDtorCounter::ctor_count, 2);
132 ASSERT_EQ(CtorDtorCounter::dtor_count, 2);
133 }
134
TEST_P(WithBoundScheduler,UnboundedPool_PolicyPreserve)135 TEST_P(WithBoundScheduler, UnboundedPool_PolicyPreserve) {
136 CtorDtorCounter::reset();
137 {
138 marl::UnboundedPool<CtorDtorCounter, marl::PoolPolicy::Preserve> pool;
139 int ctor_count;
140 {
141 auto loan = pool.borrow();
142 ASSERT_NE(CtorDtorCounter::ctor_count, 0);
143 ASSERT_EQ(CtorDtorCounter::dtor_count, 0);
144 ctor_count = CtorDtorCounter::ctor_count;
145 }
146 ASSERT_EQ(CtorDtorCounter::ctor_count, ctor_count);
147 ASSERT_EQ(CtorDtorCounter::dtor_count, 0);
148 {
149 auto loan = pool.borrow();
150 ASSERT_EQ(CtorDtorCounter::ctor_count, ctor_count);
151 ASSERT_EQ(CtorDtorCounter::dtor_count, 0);
152 }
153 ASSERT_EQ(CtorDtorCounter::ctor_count, ctor_count);
154 ASSERT_EQ(CtorDtorCounter::dtor_count, 0);
155 }
156 ASSERT_EQ(CtorDtorCounter::ctor_count, CtorDtorCounter::dtor_count);
157 }
158
TEST_P(WithBoundScheduler,BoundedPool_PolicyPreserve)159 TEST_P(WithBoundScheduler, BoundedPool_PolicyPreserve) {
160 CtorDtorCounter::reset();
161 {
162 marl::BoundedPool<CtorDtorCounter, 10, marl::PoolPolicy::Preserve> pool;
163 int ctor_count;
164 {
165 auto loan = pool.borrow();
166 ASSERT_NE(CtorDtorCounter::ctor_count, 0);
167 ASSERT_EQ(CtorDtorCounter::dtor_count, 0);
168 ctor_count = CtorDtorCounter::ctor_count;
169 }
170 ASSERT_EQ(CtorDtorCounter::ctor_count, ctor_count);
171 ASSERT_EQ(CtorDtorCounter::dtor_count, 0);
172 {
173 auto loan = pool.borrow();
174 ASSERT_EQ(CtorDtorCounter::ctor_count, ctor_count);
175 ASSERT_EQ(CtorDtorCounter::dtor_count, 0);
176 }
177 ASSERT_EQ(CtorDtorCounter::ctor_count, ctor_count);
178 ASSERT_EQ(CtorDtorCounter::dtor_count, 0);
179 }
180 ASSERT_EQ(CtorDtorCounter::ctor_count, CtorDtorCounter::dtor_count);
181 }
182
183 struct alignas(64) StructWithAlignment {
184 uint8_t i;
185 uint8_t padding[63];
186 };
187
TEST_P(WithBoundScheduler,BoundedPool_AlignedTypes)188 TEST_P(WithBoundScheduler, BoundedPool_AlignedTypes) {
189 marl::BoundedPool<StructWithAlignment, 100> pool;
190 for (int i = 0; i < 100; i++) {
191 auto loan = pool.borrow();
192 ASSERT_EQ(reinterpret_cast<uintptr_t>(&loan->i) &
193 (alignof(StructWithAlignment) - 1),
194 0U);
195 }
196 }
197
TEST_P(WithBoundScheduler,UnboundedPool_AlignedTypes)198 TEST_P(WithBoundScheduler, UnboundedPool_AlignedTypes) {
199 marl::UnboundedPool<StructWithAlignment> pool;
200 for (int i = 0; i < 100; i++) {
201 auto loan = pool.borrow();
202 ASSERT_EQ(reinterpret_cast<uintptr_t>(&loan->i) &
203 (alignof(StructWithAlignment) - 1),
204 0U);
205 }
206 }
207