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