1 #ifndef BENCHMARK_MUTEX_H_ 2 #define BENCHMARK_MUTEX_H_ 3 4 #include <mutex> 5 #include <condition_variable> 6 7 // Enable thread safety attributes only with clang. 8 // The attributes can be safely erased when compiling with other compilers. 9 #if defined(HAVE_THREAD_SAFETY_ATTRIBUTES) 10 #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) 11 #else 12 #define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op 13 #endif 14 15 #define CAPABILITY(x) \ 16 THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) 17 18 #define SCOPED_CAPABILITY \ 19 THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) 20 21 #define GUARDED_BY(x) \ 22 THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) 23 24 #define PT_GUARDED_BY(x) \ 25 THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) 26 27 #define ACQUIRED_BEFORE(...) \ 28 THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) 29 30 #define ACQUIRED_AFTER(...) \ 31 THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) 32 33 #define REQUIRES(...) \ 34 THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) 35 36 #define REQUIRES_SHARED(...) \ 37 THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) 38 39 #define ACQUIRE(...) \ 40 THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) 41 42 #define ACQUIRE_SHARED(...) \ 43 THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) 44 45 #define RELEASE(...) \ 46 THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) 47 48 #define RELEASE_SHARED(...) \ 49 THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) 50 51 #define TRY_ACQUIRE(...) \ 52 THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) 53 54 #define TRY_ACQUIRE_SHARED(...) \ 55 THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) 56 57 #define EXCLUDES(...) \ 58 THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) 59 60 #define ASSERT_CAPABILITY(x) \ 61 THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) 62 63 #define ASSERT_SHARED_CAPABILITY(x) \ 64 THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) 65 66 #define RETURN_CAPABILITY(x) \ 67 THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) 68 69 #define NO_THREAD_SAFETY_ANALYSIS \ 70 THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) 71 72 73 namespace benchmark { 74 75 typedef std::condition_variable Condition; 76 77 // NOTE: Wrappers for std::mutex and std::unique_lock are provided so that 78 // we can annotate them with thread safety attributes and use the 79 // -Wthread-safety warning with clang. The standard library types cannot be 80 // used directly because they do not provided the required annotations. 81 class CAPABILITY("mutex") Mutex 82 { 83 public: Mutex()84 Mutex() {} 85 lock()86 void lock() ACQUIRE() { mut_.lock(); } unlock()87 void unlock() RELEASE() { mut_.unlock(); } native_handle()88 std::mutex& native_handle() { 89 return mut_; 90 } 91 private: 92 std::mutex mut_; 93 }; 94 95 96 class SCOPED_CAPABILITY MutexLock 97 { 98 typedef std::unique_lock<std::mutex> MutexLockImp; 99 public: MutexLock(Mutex & m)100 MutexLock(Mutex& m) ACQUIRE(m) : ml_(m.native_handle()) 101 { } RELEASE()102 ~MutexLock() RELEASE() {} native_handle()103 MutexLockImp& native_handle() { return ml_; } 104 private: 105 MutexLockImp ml_; 106 }; 107 108 109 class Notification 110 { 111 public: Notification()112 Notification() : notified_yet_(false) { } 113 WaitForNotification()114 void WaitForNotification() const EXCLUDES(mutex_) { 115 MutexLock m_lock(mutex_); 116 auto notified_fn = [this]() REQUIRES(mutex_) { 117 return this->HasBeenNotified(); 118 }; 119 cv_.wait(m_lock.native_handle(), notified_fn); 120 } 121 Notify()122 void Notify() EXCLUDES(mutex_) { 123 { 124 MutexLock lock(mutex_); 125 notified_yet_ = 1; 126 } 127 cv_.notify_all(); 128 } 129 130 private: HasBeenNotified()131 bool HasBeenNotified() const REQUIRES(mutex_) { 132 return notified_yet_; 133 } 134 135 mutable Mutex mutex_; 136 mutable std::condition_variable cv_; 137 bool notified_yet_ GUARDED_BY(mutex_); 138 }; 139 140 } // end namespace benchmark 141 142 #endif // BENCHMARK_MUTEX_H_ 143