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 bytes_processed = 0; 46 int64_t items_processed = 0; 47 int64_t complexity_n = 0; 48 std::string report_label_; 49 std::string error_message_; 50 bool has_error_ = false; 51 UserCounters counters; 52 }; 53 GUARDED_BY(GetBenchmarkMutex()) Result results; 54 55 private: 56 mutable Mutex benchmark_mutex_; 57 std::atomic<int> alive_threads_; 58 Barrier start_stop_barrier_; 59 Mutex end_cond_mutex_; 60 Condition end_condition_; 61 }; 62 63 } // namespace internal 64 } // namespace benchmark 65 66 #endif // BENCHMARK_THREAD_MANAGER_H 67