Fix and document SkipWithError(...) using ranged-for loop.

This commit is contained in:
Eric Fiselier 2017-10-17 10:24:13 -06:00
parent a37fc0c48a
commit 22fd1a556e
2 changed files with 41 additions and 5 deletions

View File

@ -467,9 +467,13 @@ class State {
// REQUIRES: 'SkipWithError(...)' has not been called previously by the
// current thread.
// Skip any future iterations of the 'KeepRunning()' loop in the current
// thread and report an error with the specified 'msg'. After this call
// the user may explicitly 'return' from the benchmark.
// Report the benchmark as resulting in an error with the specified 'msg'.
// After this call the user may explicitly 'return' from the benchmark.
//
// If the ranged-for style of benchmark loop is used, the user must explicitly
// break from the loop, otherwise all future iterations will be run.
// If the 'KeepRunning()' loop is used the current thread will automatically
// exit the loop at the end of the current iteration.
//
// For threaded benchmarks only the current thread stops executing and future
// calls to `KeepRunning()` will block until all threads have completed
@ -611,7 +615,7 @@ struct State::StateIterator {
BENCHMARK_ALWAYS_INLINE
explicit StateIterator(State* st)
: cached_(st->max_iterations), parent_(st) {}
: cached_(st->error_occurred_ ? 0 : st->max_iterations), parent_(st) {}
public:
BENCHMARK_ALWAYS_INLINE

View File

@ -70,6 +70,15 @@ void BM_error_before_running(benchmark::State& state) {
BENCHMARK(BM_error_before_running);
ADD_CASES("BM_error_before_running", {{"", true, "error message"}});
void BM_error_before_running_range_for(benchmark::State& state) {
state.SkipWithError("error message");
for (auto _ : state) {
assert(false);
}
}
BENCHMARK(BM_error_before_running_range_for);
ADD_CASES("BM_error_before_running_range_for", {{"", true, "error message"}});
void BM_error_during_running(benchmark::State& state) {
int first_iter = true;
while (state.KeepRunning()) {
@ -93,8 +102,31 @@ ADD_CASES("BM_error_during_running", {{"/1/threads:1", true, "error message"},
{"/2/threads:4", false, ""},
{"/2/threads:8", false, ""}});
void BM_error_during_running_ranged_for(benchmark::State& state) {
assert(state.max_iterations > 3 && "test requires at least a few iterations");
int first_iter = true;
// NOTE: Users should not write the for loop explicitly.
for (auto It = state.begin(), End = state.end(); It != End; ++It) {
if (state.range(0) == 1) {
assert(first_iter);
first_iter = false;
state.SkipWithError("error message");
// Test the unfortunate but documented behavior that the ranged-for loop
// doesn't automatically terminate when SkipWithError is set.
assert(++It != End);
break; // Required behavior
}
}
}
BENCHMARK(BM_error_during_running_ranged_for)->Arg(1)->Arg(2)->Iterations(5);
ADD_CASES("BM_error_during_running_ranged_for",
{{"/1/iterations:5", true, "error message"},
{"/2/iterations:5", false, ""}});
void BM_error_after_running(benchmark::State& state) {
while (state.KeepRunning()) {
for (auto _ : state) {
benchmark::DoNotOptimize(state.iterations());
}
if (state.thread_index <= (state.threads / 2))