feat: Add ScopedPauseTiming RAII helper (#2157)

* feat: Add ScopedPauseTiming RAII helper

Adds a new `benchmark::ScopedPauseTiming` class that provides a convenient
RAII-style mechanism for pausing and resuming benchmark timers.

This is less error-prone than manually calling `PauseTiming` and
`ResumeTiming`, as it guarantees that the timer is resumed when the
scope is exited.

- Added `ScopedPauseTiming` to `include/benchmark/state.h`.
- Added a new test `test/scoped_pause_test.cc` to verify the
  functionality and prevent regressions.
- Updated `test/CMakeLists.txt` to include the new test.
- Added documentation for the new feature in `docs/user_guide.md`.

* Bump astral-sh/setup-uv from 7.6.0 to 8.0.0 (#2160)

Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 7.6.0 to 8.0.0.
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/37802adc94f370d6bfd71619e3f0bf239e1f3b78...cec208311dfd045dd5311c1add060b2062131d57)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 8.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump lukka/get-cmake from 4.3.0 to 4.3.1 (#2159)

Bumps [lukka/get-cmake](https://github.com/lukka/get-cmake) from 4.3.0 to 4.3.1.
- [Release notes](https://github.com/lukka/get-cmake/releases)
- [Changelog](https://github.com/lukka/get-cmake/blob/main/RELEASE_PROCESS.md)
- [Commits](https://github.com/lukka/get-cmake/compare/b78306120111dc2522750771cfd09ee7ca723687...ea83089aa35e08e459464341fe24ad024ee2466f)

---
updated-dependencies:
- dependency-name: lukka/get-cmake
  dependency-version: 4.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: dominic <510002+dmah42@users.noreply.github.com>

* Bump numpy from 2.4.3 to 2.4.4 in /tools (#2158)

Bumps [numpy](https://github.com/numpy/numpy) from 2.4.3 to 2.4.4.
- [Release notes](https://github.com/numpy/numpy/releases)
- [Changelog](https://github.com/numpy/numpy/blob/main/doc/RELEASE_WALKTHROUGH.rst)
- [Commits](https://github.com/numpy/numpy/compare/v2.4.3...v2.4.4)

---
updated-dependencies:
- dependency-name: numpy
  dependency-version: 2.4.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: dominic <510002+dmah42@users.noreply.github.com>

* handle move operators

* Use manual time instead of real time for better repeatability

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
diff --git a/docs/user_guide.md b/docs/user_guide.md
index c09d775..1303196 100644
--- a/docs/user_guide.md
+++ b/docs/user_guide.md
@@ -1066,6 +1066,29 @@
 ```
 <!-- {% endraw %} -->
 
+For convenience, a `ScopedPauseTiming` class is provided to manage pausing and
+resuming timers within a scope. This is less error-prone than manually calling
+`PauseTiming` and `ResumeTiming`.
+
+<!-- {% raw %} -->
+```c++
+static void BM_SetInsert_With_Scoped_Timer_Control(benchmark::State& state) {
+  std::set<int> data;
+  for (auto _ : state) {
+    {
+      benchmark::ScopedPauseTiming pause(state); // Pauses timing
+      data = ConstructRandomSet(state.range(0));
+    } // Timing resumes automatically when 'pause' goes out of scope
+
+    // The rest will be measured.
+    for (int j = 0; j < state.range(1); ++j)
+      data.insert(RandomNumber());
+  }
+}
+BENCHMARK(BM_SetInsert_With_Scoped_Timer_Control)->Ranges({{1<<10, 8<<10}, {128, 512}});
+```
+<!-- {% endraw %} -->
+
 <a name="manual-timing" />
 
 ## Manual Timing
diff --git a/include/benchmark/state.h b/include/benchmark/state.h
index e9cdf05..356c550 100644
--- a/include/benchmark/state.h
+++ b/include/benchmark/state.h
@@ -256,6 +256,23 @@
   return StateIterator();
 }
 
+class ScopedPauseTiming {
+ public:
+  explicit ScopedPauseTiming(State& state) : state_(state) {
+    state_.PauseTiming();
+  }
+  ~ScopedPauseTiming() { state_.ResumeTiming(); }
+
+  ScopedPauseTiming(const ScopedPauseTiming&) = delete;
+  void operator=(const ScopedPauseTiming&) = delete;
+
+  ScopedPauseTiming(ScopedPauseTiming&&) = delete;
+  void operator=(ScopedPauseTiming&&) = delete;
+
+ private:
+  State& state_;
+};
+
 }  // namespace benchmark
 
 #if defined(_MSC_VER)
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 2917efa..374c09f 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -225,6 +225,9 @@
 compile_output_test(locale_impermeability_test)
 benchmark_add_test(NAME locale_impermeability_test COMMAND locale_impermeability_test)
 
+compile_output_test(scoped_pause_test)
+benchmark_add_test(NAME scoped_pause_test COMMAND scoped_pause_test)
+
 ###############################################################################
 # GoogleTest Unit Tests
 ###############################################################################
diff --git a/test/scoped_pause_test.cc b/test/scoped_pause_test.cc
new file mode 100644
index 0000000..93bcfc2
--- /dev/null
+++ b/test/scoped_pause_test.cc
@@ -0,0 +1,30 @@
+
+#include <chrono>
+#include <thread>
+
+#include "benchmark/benchmark.h"
+#include "output_test.h"
+
+// BM_ScopedPause sleeps for 10ms in a ScopedPauseTiming block.
+// The reported time should be much less than 10ms.
+void BM_ScopedPause(benchmark::State& state) {
+  for (auto _ : state) {
+    benchmark::ScopedPauseTiming pause(state);
+    std::this_thread::sleep_for(std::chrono::milliseconds(10));
+    state.SetIterationTime(0.0);
+  }
+}
+BENCHMARK(BM_ScopedPause)->UseManualTime()->Iterations(1);
+
+void CheckResults(Results const& results) {
+  // Check that the real time is much less than the 10ms sleep time.
+  // Allow for up to 1ms of timing noise/overhead.
+  CHECK_FLOAT_RESULT_VALUE(results, "real_time", LT, 1e6, 0.0);
+}
+CHECK_BENCHMARK_RESULTS("BM_ScopedPause", &CheckResults);
+
+int main(int argc, char* argv[]) {
+  benchmark::MaybeReenterWithoutASLR(argc, argv);
+  RunOutputTests(argc, argv);
+  return 0;
+}