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 explicit 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 struct Result { 40 IterationCount iterations = 0; 41 double real_time_used = 0; 42 double cpu_time_used = 0; 43 double manual_time_used = 0; 44 int64_t complexity_n = 0; 45 std::string report_label_; 46 std::string skip_message_; 47 internal::Skipped skipped_ = internal::NotSkipped; 48 UserCounters counters; 49 }; 50 GUARDED_BY(GetBenchmarkMutex()) Result results; 51 52 private: 53 mutable Mutex benchmark_mutex_; 54 std::atomic<int> alive_threads_; 55 Barrier start_stop_barrier_; 56 Mutex end_cond_mutex_; 57 Condition end_condition_; 58 }; 59 60 } // namespace internal 61 } // namespace benchmark 62 63 #endif // BENCHMARK_THREAD_MANAGER_H 64