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
21TEST_P(WithBoundScheduler, UnboundedPool_ConstructDestruct) {
22 marl::UnboundedPool<int> pool;
23}
24
25TEST_P(WithBoundScheduler, BoundedPool_ConstructDestruct) {
26 marl::BoundedPool<int, 10> pool;
27}
28
29TEST_P(WithBoundScheduler, UnboundedPoolLoan_GetNull) {
30 marl::UnboundedPool<int>::Loan loan;
31 ASSERT_EQ(loan.get(), nullptr);
32}
33
34TEST_P(WithBoundScheduler, BoundedPoolLoan_GetNull) {
35 marl::BoundedPool<int, 10>::Loan loan;
36 ASSERT_EQ(loan.get(), nullptr);
37}
38
39TEST_P(WithBoundScheduler, UnboundedPool_Borrow) {
40 marl::UnboundedPool<int> pool;
41 for (int i = 0; i < 100; i++) {
42 pool.borrow();
43 }
44}
45
46TEST_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
59TEST_P(WithBoundScheduler, BoundedPool_Borrow) {
60 marl::BoundedPool<int, 100> pool;
61 for (int i = 0; i < 100; i++) {
62 pool.borrow();
63 }
64}
65
66TEST_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
79struct CtorDtorCounter {
80 CtorDtorCounter() { ctor_count++; }
81 ~CtorDtorCounter() { dtor_count++; }
82 static void reset() {
83 ctor_count = 0;
84 dtor_count = 0;
85 }
86 static int ctor_count;
87 static int dtor_count;
88};
89
90int CtorDtorCounter::ctor_count = -1;
91int CtorDtorCounter::dtor_count = -1;
92
93TEST_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
114TEST_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
135TEST_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
159TEST_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
183struct alignas(64) StructWithAlignment {
184 uint8_t i;
185 uint8_t padding[63];
186};
187
188TEST_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
198TEST_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