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 9namespace benchmark { 10namespace internal { 11 12class ThreadManager { 13 public: 14 ThreadManager(int num_threads) 15 : alive_threads_(num_threads), start_stop_barrier_(num_threads) {} 16 17 Mutex& GetBenchmarkMutex() const RETURN_CAPABILITY(benchmark_mutex_) { 18 return benchmark_mutex_; 19 } 20 21 bool StartStopBarrier() EXCLUDES(end_cond_mutex_) { 22 return start_stop_barrier_.wait(); 23 } 24 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 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