add doc
diff --git a/README.md b/README.md
index 051b301..f9f3bf4 100644
--- a/README.md
+++ b/README.md
@@ -276,6 +276,37 @@
/* BarTest is now registered */
```
+## Exiting Benchmarks in Error
+
+When external influences such as file I/O and network errors occur within
+a benchmark the `State::SkipWithError(const char* msg)` function can be used
+to skip that run of benchmark and report the error. Note that only future
+iterations of the `KeepRunning()` are skipped. Users may explicitly return
+to exit the benchmark immediately.
+
+The `SkipWithError(...)` function may be used at any point within the benchmark,
+including before and after the `KeepRunning()` loop.
+
+For example:
+
+```c++
+static void BM_test(benchmark::State& state) {
+ auto resource = GetResource();
+ if (!resource.good()) {
+ state.SkipWithError("Resource is not good!");
+ // KeepRunning() loop will not be entered.
+ }
+ while (state.KeepRunning()) {
+ auto data = resource.read_data();
+ if (!resource.good()) {
+ state.SkipWithError("Failed to read data!");
+ break; // Needed to skip the rest of the iteration.
+ }
+ do_stuff(data);
+ }
+}
+```
+
## Output Formats
The library supports multiple output formats. Use the
`--benchmark_format=<tabular|json>` flag to set the format type. `tabular` is
diff --git a/include/benchmark/benchmark_api.h b/include/benchmark/benchmark_api.h
index 654986d..7100bf5 100644
--- a/include/benchmark/benchmark_api.h
+++ b/include/benchmark/benchmark_api.h
@@ -260,13 +260,14 @@
return res;
}
- // REQUIRES: timer is running
+ // REQUIRES: timer is running and 'SkipWithError(...)' has not been called
+ // in the current thread.
// Stop the benchmark timer. If not called, the timer will be
// automatically stopped after KeepRunning() returns false for the first time.
//
// For threaded benchmarks the PauseTiming() function acts
// like a barrier. I.e., the ith call by a particular thread to this
- // function will block until all threads have made their ith call.
+ // function will block until all active threads have made their ith call.
// The timer will stop when the last thread has called this function.
//
// NOTE: PauseTiming()/ResumeTiming() are relatively
@@ -274,13 +275,14 @@
// within each benchmark iteration, if possible.
void PauseTiming();
- // REQUIRES: timer is not running
+ // REQUIRES: timer is not running and 'SkipWithError(...)' has not been called
+ // in the current thread.
// Start the benchmark timer. The timer is NOT running on entrance to the
// benchmark function. It begins running after the first call to KeepRunning()
//
// For threaded benchmarks the ResumeTiming() function acts
// like a barrier. I.e., the ith call by a particular thread to this
- // function will block until all threads have made their ith call.
+ // function will block until all active threads have made their ith call.
// The timer will start when the last thread has called this function.
//
// NOTE: PauseTiming()/ResumeTiming() are relatively
@@ -288,6 +290,21 @@
// within each benchmark iteration, if possible.
void ResumeTiming();
+ // REQUIRES: 'SkipWithError(...)' has not been called previously in 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.
+ //
+ // For threaded benchmarks only the current thread stops executing. If
+ // multiple threads report an error only the first error message will be used.
+ // The current thread is no longer considered 'active' thread by
+ // 'PauseTiming()' and 'ResumingTiming()'.
+ //
+ // NOTE: Calling 'SkipWithError(...)' does not cause the benchmark to exit
+ // the current scope immediately. If the function is called from within
+ // the 'KeepRunning()' loop the current iteration will finish. It is the users
+ // responsibility to exit the scope as needed.
void SkipWithError(const char* msg);
// REQUIRES: called exactly once per iteration of the KeepRunning loop.