| #ifndef BENCHMARK_MUTEX_H_ | 
 | #define BENCHMARK_MUTEX_H_ | 
 |  | 
 | #include <condition_variable> | 
 | #include <mutex> | 
 |  | 
 | #include "check.h" | 
 |  | 
 | // Enable thread safety attributes only with clang. | 
 | // The attributes can be safely erased when compiling with other compilers. | 
 | #if defined(HAVE_THREAD_SAFETY_ATTRIBUTES) | 
 | #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) | 
 | #else | 
 | #define THREAD_ANNOTATION_ATTRIBUTE__(x)  // no-op | 
 | #endif | 
 |  | 
 | #define CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) | 
 |  | 
 | #define SCOPED_CAPABILITY THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) | 
 |  | 
 | #define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) | 
 |  | 
 | #define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) | 
 |  | 
 | #define ACQUIRED_BEFORE(...) \ | 
 |   THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) | 
 |  | 
 | #define ACQUIRED_AFTER(...) \ | 
 |   THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) | 
 |  | 
 | #define REQUIRES(...) \ | 
 |   THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) | 
 |  | 
 | #define REQUIRES_SHARED(...) \ | 
 |   THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) | 
 |  | 
 | #define ACQUIRE(...) \ | 
 |   THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) | 
 |  | 
 | #define ACQUIRE_SHARED(...) \ | 
 |   THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) | 
 |  | 
 | #define RELEASE(...) \ | 
 |   THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) | 
 |  | 
 | #define RELEASE_SHARED(...) \ | 
 |   THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) | 
 |  | 
 | #define TRY_ACQUIRE(...) \ | 
 |   THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) | 
 |  | 
 | #define TRY_ACQUIRE_SHARED(...) \ | 
 |   THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) | 
 |  | 
 | #define EXCLUDES(...) THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) | 
 |  | 
 | #define ASSERT_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) | 
 |  | 
 | #define ASSERT_SHARED_CAPABILITY(x) \ | 
 |   THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) | 
 |  | 
 | #define RETURN_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) | 
 |  | 
 | #define NO_THREAD_SAFETY_ANALYSIS \ | 
 |   THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) | 
 |  | 
 | namespace benchmark { | 
 |  | 
 | typedef std::condition_variable Condition; | 
 |  | 
 | // NOTE: Wrappers for std::mutex and std::unique_lock are provided so that | 
 | // we can annotate them with thread safety attributes and use the | 
 | // -Wthread-safety warning with clang. The standard library types cannot be | 
 | // used directly because they do not provided the required annotations. | 
 | class CAPABILITY("mutex") Mutex { | 
 |  public: | 
 |   Mutex() {} | 
 |  | 
 |   void lock() ACQUIRE() { mut_.lock(); } | 
 |   void unlock() RELEASE() { mut_.unlock(); } | 
 |   std::mutex& native_handle() { return mut_; } | 
 |  | 
 |  private: | 
 |   std::mutex mut_; | 
 | }; | 
 |  | 
 | class SCOPED_CAPABILITY MutexLock { | 
 |   typedef std::unique_lock<std::mutex> MutexLockImp; | 
 |  | 
 |  public: | 
 |   MutexLock(Mutex& m) ACQUIRE(m) : ml_(m.native_handle()) {} | 
 |   ~MutexLock() RELEASE() {} | 
 |   MutexLockImp& native_handle() { return ml_; } | 
 |  | 
 |  private: | 
 |   MutexLockImp ml_; | 
 | }; | 
 |  | 
 | class Barrier { | 
 |  public: | 
 |   Barrier(int num_threads) : running_threads_(num_threads) {} | 
 |  | 
 |   // Called by each thread | 
 |   bool wait() EXCLUDES(lock_) { | 
 |     bool last_thread = false; | 
 |     { | 
 |       MutexLock ml(lock_); | 
 |       last_thread = createBarrier(ml); | 
 |     } | 
 |     if (last_thread) phase_condition_.notify_all(); | 
 |     return last_thread; | 
 |   } | 
 |  | 
 |   void removeThread() EXCLUDES(lock_) { | 
 |     MutexLock ml(lock_); | 
 |     --running_threads_; | 
 |     if (entered_ != 0) phase_condition_.notify_all(); | 
 |   } | 
 |  | 
 |  private: | 
 |   Mutex lock_; | 
 |   Condition phase_condition_; | 
 |   int running_threads_; | 
 |  | 
 |   // State for barrier management | 
 |   int phase_number_ = 0; | 
 |   int entered_ = 0;  // Number of threads that have entered this barrier | 
 |  | 
 |   // Enter the barrier and wait until all other threads have also | 
 |   // entered the barrier.  Returns iff this is the last thread to | 
 |   // enter the barrier. | 
 |   bool createBarrier(MutexLock& ml) REQUIRES(lock_) { | 
 |     CHECK_LT(entered_, running_threads_); | 
 |     entered_++; | 
 |     if (entered_ < running_threads_) { | 
 |       // Wait for all threads to enter | 
 |       int phase_number_cp = phase_number_; | 
 |       auto cb = [this, phase_number_cp]() { | 
 |         return this->phase_number_ > phase_number_cp || | 
 |                entered_ == running_threads_;  // A thread has aborted in error | 
 |       }; | 
 |       phase_condition_.wait(ml.native_handle(), cb); | 
 |       if (phase_number_ > phase_number_cp) return false; | 
 |       // else (running_threads_ == entered_) and we are the last thread. | 
 |     } | 
 |     // Last thread has reached the barrier | 
 |     phase_number_++; | 
 |     entered_ = 0; | 
 |     return true; | 
 |   } | 
 | }; | 
 |  | 
 | }  // end namespace benchmark | 
 |  | 
 | #endif  // BENCHMARK_MUTEX_H_ |