@@ -172,6 +172,7 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond);
172
172
173
173
#include < stdint.h>
174
174
175
+ #include < algorithm>
175
176
#include < cassert>
176
177
#include < cstddef>
177
178
#include < iosfwd>
@@ -429,16 +430,18 @@ class State {
429
430
// Returns true if the benchmark should continue through another iteration.
430
431
// NOTE: A benchmark may not return from the test until KeepRunning() has
431
432
// returned false.
432
- bool KeepRunning () {
433
- if (BENCHMARK_BUILTIN_EXPECT (!started_, false )) {
434
- StartKeepRunning ();
435
- }
436
- bool const res = (--total_iterations_ != 0 );
437
- if (BENCHMARK_BUILTIN_EXPECT (!res, false )) {
438
- FinishKeepRunning ();
439
- }
440
- return res;
441
- }
433
+ bool KeepRunning ();
434
+
435
+ // Returns true iff the benchmark should run n more iterations.
436
+ // NOTE: A benchmark must not return from the test until KeepRunningBatch()
437
+ // has returned false.
438
+ // NOTE: KeepRunningBatch() may overshoot by up to 'n' iterations.
439
+ //
440
+ // Intended usage:
441
+ // while (state.KeepRunningBatch(1000)) {
442
+ // // process 1000 elements
443
+ // }
444
+ bool KeepRunningBatch (int n);
442
445
443
446
// REQUIRES: timer is running and 'SkipWithError(...)' has not been called
444
447
// by the current thread.
@@ -565,12 +568,15 @@ class State {
565
568
int range_y () const { return range (1 ); }
566
569
567
570
BENCHMARK_ALWAYS_INLINE
568
- size_t iterations () const { return (max_iterations - total_iterations_) + 1 ; }
571
+ size_t iterations () const { return (completed_iterations_ - total_iterations_); }
569
572
570
573
private:
571
574
bool started_;
572
575
bool finished_;
576
+ // When total_iterations_ is 0, KeepRunning() and friends will return false.
573
577
size_t total_iterations_;
578
+ // May be larger than max_iterations.
579
+ size_t completed_iterations_;
574
580
575
581
std::vector<int > range_;
576
582
@@ -581,6 +587,11 @@ class State {
581
587
582
588
bool error_occurred_;
583
589
590
+ // When using KeepRunningBatch(), batch_leftover_ holds the number of
591
+ // iterations beyond max_iters that were run. Used to track
592
+ // completed_iterations_ accurately.
593
+ size_t batch_leftover_;
594
+
584
595
public:
585
596
// Container for user-defined counters.
586
597
UserCounters counters;
@@ -597,12 +608,43 @@ class State {
597
608
598
609
private:
599
610
void StartKeepRunning ();
600
- void FinishKeepRunning ();
611
+ void FinishKeepRunning (size_t n );
601
612
internal::ThreadTimer* timer_;
602
613
internal::ThreadManager* manager_;
603
614
BENCHMARK_DISALLOW_COPY_AND_ASSIGN (State);
604
615
};
605
616
617
+ BENCHMARK_ALWAYS_INLINE
618
+ inline bool State::KeepRunningBatch (int n) {
619
+ if (BENCHMARK_BUILTIN_EXPECT (!started_, false )) {
620
+ StartKeepRunning ();
621
+ }
622
+ // leftover only has a sensible value when n > total_iterations.
623
+ size_t leftover = n - total_iterations_;
624
+ // total_iterations_ is a size_t. Avoid wrapping around past 0.
625
+ bool const res = (total_iterations_ > 0 );
626
+ total_iterations_ -= std::min<size_t >(n, total_iterations_);
627
+ if (BENCHMARK_BUILTIN_EXPECT (!res, false )) {
628
+ FinishKeepRunning (batch_leftover_);
629
+ }
630
+ // If this batch has 0 < n < total_iterations iterations, (i.e. it's the last
631
+ // batch), track how many extra iterations past max_iters we ran.
632
+ batch_leftover_ = leftover;
633
+ return res;
634
+ }
635
+
636
+ BENCHMARK_ALWAYS_INLINE
637
+ inline bool State::KeepRunning () {
638
+ if (BENCHMARK_BUILTIN_EXPECT (!started_, false )) {
639
+ StartKeepRunning ();
640
+ }
641
+ bool const res = (total_iterations_-- != 0 );
642
+ if (BENCHMARK_BUILTIN_EXPECT (!res, false )) {
643
+ FinishKeepRunning (0 );
644
+ }
645
+ return res;
646
+ }
647
+
606
648
struct State ::StateIterator {
607
649
struct BENCHMARK_UNUSED Value {};
608
650
typedef std::forward_iterator_tag iterator_category;
@@ -633,7 +675,7 @@ struct State::StateIterator {
633
675
BENCHMARK_ALWAYS_INLINE
634
676
bool operator !=(StateIterator const &) const {
635
677
if (BENCHMARK_BUILTIN_EXPECT (cached_ != 0 , true )) return true ;
636
- parent_->FinishKeepRunning ();
678
+ parent_->FinishKeepRunning (0 );
637
679
return false ;
638
680
}
639
681
0 commit comments