1a8c51b3fSopenharmony_ci#ifndef BENCHMARK_THREAD_MANAGER_H
2a8c51b3fSopenharmony_ci#define BENCHMARK_THREAD_MANAGER_H
3a8c51b3fSopenharmony_ci
4a8c51b3fSopenharmony_ci#include <atomic>
5a8c51b3fSopenharmony_ci
6a8c51b3fSopenharmony_ci#include "benchmark/benchmark.h"
7a8c51b3fSopenharmony_ci#include "mutex.h"
8a8c51b3fSopenharmony_ci
9a8c51b3fSopenharmony_cinamespace benchmark {
10a8c51b3fSopenharmony_cinamespace internal {
11a8c51b3fSopenharmony_ci
12a8c51b3fSopenharmony_ciclass ThreadManager {
13a8c51b3fSopenharmony_ci public:
14a8c51b3fSopenharmony_ci  explicit ThreadManager(int num_threads)
15a8c51b3fSopenharmony_ci      : alive_threads_(num_threads), start_stop_barrier_(num_threads) {}
16a8c51b3fSopenharmony_ci
17a8c51b3fSopenharmony_ci  Mutex& GetBenchmarkMutex() const RETURN_CAPABILITY(benchmark_mutex_) {
18a8c51b3fSopenharmony_ci    return benchmark_mutex_;
19a8c51b3fSopenharmony_ci  }
20a8c51b3fSopenharmony_ci
21a8c51b3fSopenharmony_ci  bool StartStopBarrier() EXCLUDES(end_cond_mutex_) {
22a8c51b3fSopenharmony_ci    return start_stop_barrier_.wait();
23a8c51b3fSopenharmony_ci  }
24a8c51b3fSopenharmony_ci
25a8c51b3fSopenharmony_ci  void NotifyThreadComplete() EXCLUDES(end_cond_mutex_) {
26a8c51b3fSopenharmony_ci    start_stop_barrier_.removeThread();
27a8c51b3fSopenharmony_ci    if (--alive_threads_ == 0) {
28a8c51b3fSopenharmony_ci      MutexLock lock(end_cond_mutex_);
29a8c51b3fSopenharmony_ci      end_condition_.notify_all();
30a8c51b3fSopenharmony_ci    }
31a8c51b3fSopenharmony_ci  }
32a8c51b3fSopenharmony_ci
33a8c51b3fSopenharmony_ci  void WaitForAllThreads() EXCLUDES(end_cond_mutex_) {
34a8c51b3fSopenharmony_ci    MutexLock lock(end_cond_mutex_);
35a8c51b3fSopenharmony_ci    end_condition_.wait(lock.native_handle(),
36a8c51b3fSopenharmony_ci                        [this]() { return alive_threads_ == 0; });
37a8c51b3fSopenharmony_ci  }
38a8c51b3fSopenharmony_ci
39a8c51b3fSopenharmony_ci  struct Result {
40a8c51b3fSopenharmony_ci    IterationCount iterations = 0;
41a8c51b3fSopenharmony_ci    double real_time_used = 0;
42a8c51b3fSopenharmony_ci    double cpu_time_used = 0;
43a8c51b3fSopenharmony_ci    double manual_time_used = 0;
44a8c51b3fSopenharmony_ci    int64_t complexity_n = 0;
45a8c51b3fSopenharmony_ci    std::string report_label_;
46a8c51b3fSopenharmony_ci    std::string skip_message_;
47a8c51b3fSopenharmony_ci    internal::Skipped skipped_ = internal::NotSkipped;
48a8c51b3fSopenharmony_ci    UserCounters counters;
49a8c51b3fSopenharmony_ci  };
50a8c51b3fSopenharmony_ci  GUARDED_BY(GetBenchmarkMutex()) Result results;
51a8c51b3fSopenharmony_ci
52a8c51b3fSopenharmony_ci private:
53a8c51b3fSopenharmony_ci  mutable Mutex benchmark_mutex_;
54a8c51b3fSopenharmony_ci  std::atomic<int> alive_threads_;
55a8c51b3fSopenharmony_ci  Barrier start_stop_barrier_;
56a8c51b3fSopenharmony_ci  Mutex end_cond_mutex_;
57a8c51b3fSopenharmony_ci  Condition end_condition_;
58a8c51b3fSopenharmony_ci};
59a8c51b3fSopenharmony_ci
60a8c51b3fSopenharmony_ci}  // namespace internal
61a8c51b3fSopenharmony_ci}  // namespace benchmark
62a8c51b3fSopenharmony_ci
63a8c51b3fSopenharmony_ci#endif  // BENCHMARK_THREAD_MANAGER_H
64