Merge  branch 'upstream/master' into v2
diff --git a/.gitignore b/.gitignore
index bfc6b57..93d5ced 100644
--- a/.gitignore
+++ b/.gitignore
@@ -45,6 +45,9 @@
 build/
 _build/
 
-# in-source dependancies
+# in-source dependencies
 /googletest/
 
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+CMakeSettings.json
diff --git a/include/benchmark/benchmark.h b/include/benchmark/benchmark.h
index a59bd6e..1946d30 100644
--- a/include/benchmark/benchmark.h
+++ b/include/benchmark/benchmark.h
@@ -172,6 +172,7 @@
 
 #include <stdint.h>
 
+#include <algorithm>
 #include <cassert>
 #include <cstddef>
 #include <iosfwd>
@@ -481,16 +482,18 @@
   // Returns true if the benchmark should continue through another iteration.
   // NOTE: A benchmark may not return from the test until KeepRunning() has
   // returned false.
-  bool KeepRunning() {
-    if (BENCHMARK_BUILTIN_EXPECT(!started_, false)) {
-      StartKeepRunning();
-    }
-    bool const res = (--total_iterations_ != 0);
-    if (BENCHMARK_BUILTIN_EXPECT(!res, false)) {
-      FinishKeepRunning();
-    }
-    return res;
-  }
+  bool KeepRunning();
+
+  // Returns true iff the benchmark should run n more iterations.
+  // NOTE: A benchmark must not return from the test until KeepRunningBatch()
+  // has returned false.
+  // NOTE: KeepRunningBatch() may overshoot by up to 'n' iterations.
+  //
+  // Intended usage:
+  //   while (state.KeepRunningBatch(1000)) {
+  //     // process 1000 elements
+  //   }
+  bool KeepRunningBatch(size_t n);
 
   // REQUIRES: timer is running and 'SkipWithError(...)' has not been called
   //           by the current thread.
@@ -635,12 +638,16 @@
   int range_y() const { return range(1); }
 
   BENCHMARK_ALWAYS_INLINE
-  size_t iterations() const { return (max_iterations - total_iterations_) + 1; }
+  size_t iterations() const {
+    return (max_iterations - total_iterations_ + batch_leftover_);
+  }
 
  private:
   bool started_;
   bool finished_;
+  // When total_iterations_ is 0, KeepRunning() and friends will return false.
   size_t total_iterations_;
+  // May be larger than max_iterations.
 
   std::vector<int> range_;
   internal::JSONPointer json_input_;
@@ -653,6 +660,11 @@
 
   bool error_occurred_;
 
+  // When using KeepRunningBatch(), batch_leftover_ holds the number of
+  // iterations beyond max_iters that were run. Used to track
+  // completed_iterations_ accurately.
+  size_t batch_leftover_;
+
  public:
   // Container for user-defined counters.
   UserCounters counters;
@@ -675,6 +687,50 @@
   BENCHMARK_DISALLOW_COPY_AND_ASSIGN(State);
 };
 
+inline BENCHMARK_ALWAYS_INLINE
+bool State::KeepRunning() {
+  // total_iterations_ is set to 0 by the constructor, and always set to a
+  // nonzero value by StartKepRunning().
+  if (BENCHMARK_BUILTIN_EXPECT(total_iterations_ != 0, true)) {
+    --total_iterations_;
+    return true;
+  }
+  if (!started_) {
+    StartKeepRunning();
+    if (!error_occurred_) {
+      // max_iterations > 0. The first iteration is always valid.
+      --total_iterations_;
+      return true;
+    }
+  }
+  FinishKeepRunning();
+  return false;
+}
+
+inline BENCHMARK_ALWAYS_INLINE
+bool State::KeepRunningBatch(size_t n) {
+  // total_iterations_ is set to 0 by the constructor, and always set to a
+  // nonzero value by StartKepRunning().
+  if (BENCHMARK_BUILTIN_EXPECT(total_iterations_ >= n, true)) {
+    total_iterations_ -= n;
+    return true;
+  }
+  if (!started_) {
+    StartKeepRunning();
+    if (!error_occurred_ && total_iterations_ >= n) {
+      total_iterations_-= n;
+      return true;
+    }
+  }
+  if (total_iterations_ != 0) {
+    batch_leftover_  = n - total_iterations_;
+    total_iterations_ = 0;
+    return true;
+  }
+  FinishKeepRunning();
+  return false;
+}
+
 struct State::StateIterator {
   struct BENCHMARK_UNUSED Value {};
   typedef std::forward_iterator_tag iterator_category;
diff --git a/src/benchmark.cc b/src/benchmark.cc
index 43d4f8f..f04e2f7 100644
--- a/src/benchmark.cc
+++ b/src/benchmark.cc
@@ -280,7 +280,7 @@
   State st(iters, b->arg, internal::JSONPointer(b->json_arg), thread_id,
            b->threads, &timer, manager);
   b->benchmark->Run(st);
-  CHECK(st.iterations() == st.max_iterations)
+  CHECK(st.iterations() >= st.max_iterations)
       << "Benchmark returned before State::KeepRunning() returned false!";
   {
     MutexLock l(manager->GetBenchmarkMutex());
@@ -421,7 +421,7 @@
              internal::ThreadManager* manager)
     : started_(false),
       finished_(false),
-      total_iterations_(max_iters + 1),
+      total_iterations_(0),
       range_(ranges),
       json_input_(std::move(json_ptr)),
       json_output_(json::object_t{}),
@@ -429,6 +429,7 @@
       items_processed_(0),
       complexity_n_(0),
       error_occurred_(false),
+      batch_leftover_(0),
       counters(),
       thread_index(thread_i),
       threads(n_threads),
@@ -436,7 +437,6 @@
       timer_(timer),
       manager_(manager) {
   CHECK(max_iterations != 0) << "At least one iteration must be run";
-  CHECK(total_iterations_ != 0) << "max iterations wrapped around";
   CHECK_LT(thread_index, threads) << "thread_index must be less than threads";
 }
 
@@ -461,7 +461,7 @@
       manager_->results.has_error_ = true;
     }
   }
-  total_iterations_ = 1;
+  total_iterations_ = 0;
   if (timer_->running()) timer_->StopTimer();
 }
 
@@ -477,6 +477,7 @@
 void State::StartKeepRunning() {
   CHECK(!started_ && !finished_);
   started_ = true;
+  total_iterations_ = error_occurred_ ? 0 : max_iterations;
   manager_->StartStopBarrier();
   if (!error_occurred_) ResumeTiming();
 }
@@ -486,8 +487,8 @@
   if (!error_occurred_) {
     PauseTiming();
   }
-  // Total iterations has now wrapped around zero. Fix this.
-  total_iterations_ = 1;
+  // Total iterations has now wrapped around past 0. Fix this.
+  total_iterations_ = 0;
   finished_ = true;
   manager_->StartStopBarrier();
 }
diff --git a/src/internal_macros.h b/src/internal_macros.h
index 6cdb3c2..c34f571 100644
--- a/src/internal_macros.h
+++ b/src/internal_macros.h
@@ -11,29 +11,35 @@
 #endif
 
 #if defined(__clang__)
-#define COMPILER_CLANG
+  #if !defined(COMPILER_CLANG)
+    #define COMPILER_CLANG
+  #endif
 #elif defined(_MSC_VER)
-#define COMPILER_MSVC
+  #if !defined(COMPILER_MSVC)
+    #define COMPILER_MSVC
+  #endif
 #elif defined(__GNUC__)
-#define COMPILER_GCC
+  #if !defined(COMPILER_GCC)
+    #define COMPILER_GCC
+  #endif
 #endif
 
 #if __has_feature(cxx_attributes)
-#define BENCHMARK_NORETURN [[noreturn]]
+  #define BENCHMARK_NORETURN [[noreturn]]
 #elif defined(__GNUC__)
-#define BENCHMARK_NORETURN __attribute__((noreturn))
+  #define BENCHMARK_NORETURN __attribute__((noreturn))
 #elif defined(COMPILER_MSVC)
-#define BENCHMARK_NORETURN __declspec(noreturn)
+  #define BENCHMARK_NORETURN __declspec(noreturn)
 #else
-#define BENCHMARK_NORETURN
+  #define BENCHMARK_NORETURN
 #endif
 
 #if defined(__CYGWIN__)
-#define BENCHMARK_OS_CYGWIN 1
+  #define BENCHMARK_OS_CYGWIN 1
 #elif defined(_WIN32)
-#define BENCHMARK_OS_WINDOWS 1
+  #define BENCHMARK_OS_WINDOWS 1
 #elif defined(__APPLE__)
-#include "TargetConditionals.h"
+  #include "TargetConditionals.h"
   #if defined(TARGET_OS_MAC)
     #define BENCHMARK_OS_MACOSX 1
     #if defined(TARGET_OS_IPHONE)
@@ -41,36 +47,36 @@
     #endif
   #endif
 #elif defined(__FreeBSD__)
-#define BENCHMARK_OS_FREEBSD 1
+  #define BENCHMARK_OS_FREEBSD 1
 #elif defined(__NetBSD__)
-#define BENCHMARK_OS_NETBSD 1
+  #define BENCHMARK_OS_NETBSD 1
 #elif defined(__linux__)
-#define BENCHMARK_OS_LINUX 1
+  #define BENCHMARK_OS_LINUX 1
 #elif defined(__native_client__)
-#define BENCHMARK_OS_NACL 1
+  #define BENCHMARK_OS_NACL 1
 #elif defined(EMSCRIPTEN)
-#define BENCHMARK_OS_EMSCRIPTEN 1
+  #define BENCHMARK_OS_EMSCRIPTEN 1
 #elif defined(__rtems__)
-#define BENCHMARK_OS_RTEMS 1
+  #define BENCHMARK_OS_RTEMS 1
 #endif
 
 #if !__has_feature(cxx_exceptions) && !defined(__cpp_exceptions) \
      && !defined(__EXCEPTIONS)
-#define BENCHMARK_HAS_NO_EXCEPTIONS
+  #define BENCHMARK_HAS_NO_EXCEPTIONS
 #endif
 
 #if defined(COMPILER_CLANG) || defined(COMPILER_GCC)
-#define BENCHMARK_MAYBE_UNUSED __attribute__((unused))
+  #define BENCHMARK_MAYBE_UNUSED __attribute__((unused))
 #else
-#define BENCHMARK_MAYBE_UNUSED
+  #define BENCHMARK_MAYBE_UNUSED
 #endif
 
 #if defined(COMPILER_GCC) || __has_builtin(__builtin_unreachable)
-#define BENCHMARK_UNREACHABLE() __builtin_unreachable()
+  #define BENCHMARK_UNREACHABLE() __builtin_unreachable()
 #elif defined(COMPILER_MSVC)
-#define BENCHMARK_UNREACHABLE() __assume(false)
+  #define BENCHMARK_UNREACHABLE() __assume(false)
 #else
-#define BENCHMARK_UNREACHABLE() ((void)0)
+  #define BENCHMARK_UNREACHABLE() ((void)0)
 #endif
 
 #endif  // BENCHMARK_INTERNAL_MACROS_H_
diff --git a/src/statistics.cc b/src/statistics.cc
index 5932ad4..d284367 100644
--- a/src/statistics.cc
+++ b/src/statistics.cc
@@ -30,7 +30,7 @@
 };
 
 double StatisticsMean(const std::vector<double>& v) {
-  if (v.size() == 0) return 0.0;
+  if (v.empty()) return 0.0;
   return StatisticsSum(v) * (1.0 / v.size());
 }
 
@@ -62,7 +62,7 @@
 
 double StatisticsStdDev(const std::vector<double>& v) {
   const auto mean = StatisticsMean(v);
-  if (v.size() == 0) return mean;
+  if (v.empty()) return mean;
 
   // Sample standard deviation is undefined for n = 1
   if (v.size() == 1)
diff --git a/src/sysinfo.cc b/src/sysinfo.cc
index 2520ad5..90be166 100644
--- a/src/sysinfo.cc
+++ b/src/sysinfo.cc
@@ -303,7 +303,7 @@
     if (!B.test(0)) continue;
     CInfo* Cache = &it->Cache;
     CPUInfo::CacheInfo C;
-    C.num_sharing = B.count();
+    C.num_sharing = static_cast<int>(B.count());
     C.level = Cache->Level;
     C.size = Cache->Size;
     switch (Cache->Type) {
diff --git a/test/basic_test.cc b/test/basic_test.cc
index 3348781..12579c0 100644
--- a/test/basic_test.cc
+++ b/test/basic_test.cc
@@ -102,10 +102,21 @@
   while (state.KeepRunning()) {
     ++iter_count;
   }
-  assert(iter_count == state.max_iterations);
+  assert(iter_count == state.iterations());
 }
 BENCHMARK(BM_KeepRunning);
 
+void BM_KeepRunningBatch(benchmark::State& state) {
+  // Choose a prime batch size to avoid evenly dividing max_iterations.
+  const size_t batch_size = 101;
+  size_t iter_count = 0;
+  while (state.KeepRunningBatch(batch_size)) {
+    iter_count += batch_size;
+  }
+  assert(state.iterations() == iter_count);
+}
+BENCHMARK(BM_KeepRunningBatch);
+
 void BM_RangedFor(benchmark::State& state) {
   size_t iter_count = 0;
   for (auto _ : state) {
diff --git a/test/skip_with_error_test.cc b/test/skip_with_error_test.cc
index 0c2f348..8d2c342 100644
--- a/test/skip_with_error_test.cc
+++ b/test/skip_with_error_test.cc
@@ -70,6 +70,16 @@
 BENCHMARK(BM_error_before_running);
 ADD_CASES("BM_error_before_running", {{"", true, "error message"}});
 
+
+void BM_error_before_running_batch(benchmark::State& state) {
+  state.SkipWithError("error message");
+  while (state.KeepRunningBatch(17)) {
+    assert(false);
+  }
+}
+BENCHMARK(BM_error_before_running_batch);
+ADD_CASES("BM_error_before_running_batch", {{"", true, "error message"}});
+
 void BM_error_before_running_range_for(benchmark::State& state) {
   state.SkipWithError("error message");
   for (auto _ : state) {