Skip to content

Commit ff5c94d

Browse files
authored
change setup and teardown callback type (#1934)
Change type of callbacks to take `std::function`
1 parent 8d4fdd6 commit ff5c94d

File tree

6 files changed

+156
-17
lines changed

6 files changed

+156
-17
lines changed

include/benchmark/benchmark.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond);
169169
#include <atomic>
170170
#include <cassert>
171171
#include <cstddef>
172+
#include <functional>
172173
#include <initializer_list>
173174
#include <iosfwd>
174175
#include <limits>
@@ -303,6 +304,10 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond);
303304

304305
namespace benchmark {
305306
class BenchmarkReporter;
307+
class State;
308+
309+
// Define alias of Setup/Teardown callback function type
310+
using callback_function = std::function<void(const benchmark::State&)>;
306311

307312
// Default number of minimum benchmark running time in seconds.
308313
const char kDefaultMinTimeStr[] = "0.5s";
@@ -1157,10 +1162,10 @@ class BENCHMARK_EXPORT Benchmark {
11571162
//
11581163
// The callback will be passed a State object, which includes the number
11591164
// of threads, thread-index, benchmark arguments, etc.
1160-
//
1161-
// The callback must not be NULL or self-deleting.
1162-
Benchmark* Setup(void (*setup)(const benchmark::State&));
1163-
Benchmark* Teardown(void (*teardown)(const benchmark::State&));
1165+
Benchmark* Setup(callback_function&&);
1166+
Benchmark* Setup(const callback_function&);
1167+
Benchmark* Teardown(callback_function&&);
1168+
Benchmark* Teardown(const callback_function&);
11641169

11651170
// Pass this benchmark object to *func, which can customize
11661171
// the benchmark by calling various methods like Arg, Args,
@@ -1309,7 +1314,6 @@ class BENCHMARK_EXPORT Benchmark {
13091314
std::vector<Statistics> statistics_;
13101315
std::vector<int> thread_counts_;
13111316

1312-
typedef void (*callback_function)(const benchmark::State&);
13131317
callback_function setup_;
13141318
callback_function teardown_;
13151319

src/benchmark_api_internal.cc

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ BenchmarkInstance::BenchmarkInstance(Benchmark* benchmark, int family_idx,
2727
min_time_(benchmark_.min_time_),
2828
min_warmup_time_(benchmark_.min_warmup_time_),
2929
iterations_(benchmark_.iterations_),
30-
threads_(thread_count) {
30+
threads_(thread_count),
31+
setup_(benchmark_.setup_),
32+
teardown_(benchmark_.teardown_) {
3133
name_.function_name = benchmark_.name_;
3234

3335
size_t arg_i = 0;
@@ -84,9 +86,6 @@ BenchmarkInstance::BenchmarkInstance(Benchmark* benchmark, int family_idx,
8486
if (!benchmark_.thread_counts_.empty()) {
8587
name_.threads = StrFormat("threads:%d", threads_);
8688
}
87-
88-
setup_ = benchmark_.setup_;
89-
teardown_ = benchmark_.teardown_;
9089
}
9190

9291
State BenchmarkInstance::Run(

src/benchmark_api_internal.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,8 @@ class BenchmarkInstance {
6868
IterationCount iterations_;
6969
int threads_; // Number of concurrent threads to us
7070

71-
typedef void (*callback_function)(const benchmark::State&);
72-
callback_function setup_ = nullptr;
73-
callback_function teardown_ = nullptr;
71+
callback_function setup_;
72+
callback_function teardown_;
7473
};
7574

7675
bool FindBenchmarksInternal(const std::string& re,

src/benchmark_register.cc

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -224,9 +224,7 @@ Benchmark::Benchmark(const std::string& name)
224224
use_real_time_(false),
225225
use_manual_time_(false),
226226
complexity_(oNone),
227-
complexity_lambda_(nullptr),
228-
setup_(nullptr),
229-
teardown_(nullptr) {
227+
complexity_lambda_(nullptr) {
230228
ComputeStatistics("mean", StatisticsMean);
231229
ComputeStatistics("median", StatisticsMedian);
232230
ComputeStatistics("stddev", StatisticsStdDev);
@@ -337,13 +335,25 @@ Benchmark* Benchmark::Apply(void (*custom_arguments)(Benchmark* benchmark)) {
337335
return this;
338336
}
339337

340-
Benchmark* Benchmark::Setup(void (*setup)(const benchmark::State&)) {
338+
Benchmark* Benchmark::Setup(callback_function&& setup) {
339+
BM_CHECK(setup != nullptr);
340+
setup_ = std::forward<callback_function>(setup);
341+
return this;
342+
}
343+
344+
Benchmark* Benchmark::Setup(const callback_function& setup) {
341345
BM_CHECK(setup != nullptr);
342346
setup_ = setup;
343347
return this;
344348
}
345349

346-
Benchmark* Benchmark::Teardown(void (*teardown)(const benchmark::State&)) {
350+
Benchmark* Benchmark::Teardown(callback_function&& teardown) {
351+
BM_CHECK(teardown != nullptr);
352+
teardown_ = std::forward<callback_function>(teardown);
353+
return this;
354+
}
355+
356+
Benchmark* Benchmark::Teardown(const callback_function& teardown) {
347357
BM_CHECK(teardown != nullptr);
348358
teardown_ = teardown;
349359
return this;

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ if (BENCHMARK_ENABLE_GTEST_TESTS)
232232
add_gtest(time_unit_gtest)
233233
add_gtest(min_time_parse_gtest)
234234
add_gtest(profiler_manager_gtest)
235+
add_gtest(benchmark_setup_teardown_cb_types_gtest)
235236
endif(BENCHMARK_ENABLE_GTEST_TESTS)
236237

237238
###############################################################################
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#include "benchmark/benchmark.h"
2+
#include "gtest/gtest.h"
3+
4+
using benchmark::BenchmarkReporter;
5+
using benchmark::callback_function;
6+
using benchmark::ClearRegisteredBenchmarks;
7+
using benchmark::RegisterBenchmark;
8+
using benchmark::RunSpecifiedBenchmarks;
9+
using benchmark::State;
10+
using benchmark::internal::Benchmark;
11+
12+
static int functor_called = 0;
13+
struct Functor {
14+
void operator()(const benchmark::State& /*unused*/) { functor_called++; }
15+
};
16+
17+
class NullReporter : public BenchmarkReporter {
18+
public:
19+
bool ReportContext(const Context& /*context*/) override { return true; }
20+
void ReportRuns(const std::vector<Run>& /* report */) override {}
21+
};
22+
23+
class BenchmarkTest : public testing::Test {
24+
public:
25+
Benchmark* bm;
26+
NullReporter null_reporter;
27+
28+
int setup_calls;
29+
int teardown_calls;
30+
31+
void SetUp() override {
32+
setup_calls = 0;
33+
teardown_calls = 0;
34+
functor_called = 0;
35+
36+
bm = RegisterBenchmark("BM", [](State& st) {
37+
for (auto _ : st) {
38+
}
39+
});
40+
bm->Iterations(1);
41+
}
42+
43+
void TearDown() override { ClearRegisteredBenchmarks(); }
44+
};
45+
46+
// Test that Setup/Teardown can correctly take a lambda expressions
47+
TEST_F(BenchmarkTest, LambdaTestCopy) {
48+
auto setup_lambda = [this](const State&) { setup_calls++; };
49+
auto teardown_lambda = [this](const State&) { teardown_calls++; };
50+
bm->Setup(setup_lambda);
51+
bm->Teardown(teardown_lambda);
52+
RunSpecifiedBenchmarks(&null_reporter);
53+
EXPECT_EQ(setup_calls, 1);
54+
EXPECT_EQ(teardown_calls, 1);
55+
}
56+
57+
// Test that Setup/Teardown can correctly take a lambda expressions
58+
TEST_F(BenchmarkTest, LambdaTestMove) {
59+
auto setup_lambda = [this](const State&) { setup_calls++; };
60+
auto teardown_lambda = [this](const State&) { teardown_calls++; };
61+
bm->Setup(std::move(setup_lambda));
62+
bm->Teardown(std::move(teardown_lambda));
63+
RunSpecifiedBenchmarks(&null_reporter);
64+
EXPECT_EQ(setup_calls, 1);
65+
EXPECT_EQ(teardown_calls, 1);
66+
}
67+
68+
// Test that Setup/Teardown can correctly take std::function
69+
TEST_F(BenchmarkTest, CallbackFunctionCopy) {
70+
callback_function setup_lambda = [this](const State&) { setup_calls++; };
71+
callback_function teardown_lambda = [this](const State&) {
72+
teardown_calls++;
73+
};
74+
bm->Setup(setup_lambda);
75+
bm->Teardown(teardown_lambda);
76+
RunSpecifiedBenchmarks(&null_reporter);
77+
EXPECT_EQ(setup_calls, 1);
78+
EXPECT_EQ(teardown_calls, 1);
79+
}
80+
81+
// Test that Setup/Teardown can correctly take std::function
82+
TEST_F(BenchmarkTest, CallbackFunctionMove) {
83+
callback_function setup_lambda = [this](const State&) { setup_calls++; };
84+
callback_function teardown_lambda = [this](const State&) {
85+
teardown_calls++;
86+
};
87+
bm->Setup(std::move(setup_lambda));
88+
bm->Teardown(std::move(teardown_lambda));
89+
RunSpecifiedBenchmarks(&null_reporter);
90+
EXPECT_EQ(setup_calls, 1);
91+
EXPECT_EQ(teardown_calls, 1);
92+
}
93+
94+
// Test that Setup/Teardown can correctly take functors
95+
TEST_F(BenchmarkTest, FunctorCopy) {
96+
Functor func;
97+
bm->Setup(func);
98+
bm->Teardown(func);
99+
RunSpecifiedBenchmarks(&null_reporter);
100+
EXPECT_EQ(functor_called, 2);
101+
}
102+
103+
// Test that Setup/Teardown can correctly take functors
104+
TEST_F(BenchmarkTest, FunctorMove) {
105+
Functor func1;
106+
Functor func2;
107+
bm->Setup(std::move(func1));
108+
bm->Teardown(std::move(func2));
109+
RunSpecifiedBenchmarks(&null_reporter);
110+
EXPECT_EQ(functor_called, 2);
111+
}
112+
113+
// Test that Setup/Teardown can not take nullptr
114+
TEST_F(BenchmarkTest, NullptrTest) {
115+
#if GTEST_HAS_DEATH_TEST
116+
// Tests only runnable in debug mode (when BM_CHECK is enabled).
117+
#ifndef NDEBUG
118+
#ifndef TEST_BENCHMARK_LIBRARY_HAS_NO_ASSERTIONS
119+
EXPECT_DEATH(bm->Setup(nullptr), "setup != nullptr");
120+
EXPECT_DEATH(bm->Teardown(nullptr), "teardown != nullptr");
121+
#else
122+
GTEST_SKIP() << "Test skipped because BM_CHECK is disabled";
123+
#endif
124+
#endif
125+
#endif
126+
}

0 commit comments

Comments
 (0)