benchmark
1.6.1
Toggle main menu visibility
Loading...
Searching...
No Matches
mutex.h
1
#ifndef BENCHMARK_MUTEX_H_
2
#define BENCHMARK_MUTEX_H_
3
4
#include <condition_variable>
5
#include <mutex>
6
7
#include "check.h"
8
9
// Enable thread safety attributes only with clang.
10
// The attributes can be safely erased when compiling with other compilers.
11
#if defined(HAVE_THREAD_SAFETY_ATTRIBUTES)
12
#define THREAD_ANNOTATION_ATTRIBUTE_(x) __attribute__((x))
13
#else
14
#define THREAD_ANNOTATION_ATTRIBUTE_(x)
// no-op
15
#endif
16
17
#define CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE_(capability(x))
18
19
#define SCOPED_CAPABILITY THREAD_ANNOTATION_ATTRIBUTE_(scoped_lockable)
20
21
#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE_(guarded_by(x))
22
23
#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE_(pt_guarded_by(x))
24
25
#define ACQUIRED_BEFORE(...) \
26
THREAD_ANNOTATION_ATTRIBUTE_(acquired_before(__VA_ARGS__))
27
28
#define ACQUIRED_AFTER(...) \
29
THREAD_ANNOTATION_ATTRIBUTE_(acquired_after(__VA_ARGS__))
30
31
#define REQUIRES(...) \
32
THREAD_ANNOTATION_ATTRIBUTE_(requires_capability(__VA_ARGS__))
33
34
#define REQUIRES_SHARED(...) \
35
THREAD_ANNOTATION_ATTRIBUTE_(requires_shared_capability(__VA_ARGS__))
36
37
#define ACQUIRE(...) \
38
THREAD_ANNOTATION_ATTRIBUTE_(acquire_capability(__VA_ARGS__))
39
40
#define ACQUIRE_SHARED(...) \
41
THREAD_ANNOTATION_ATTRIBUTE_(acquire_shared_capability(__VA_ARGS__))
42
43
#define RELEASE(...) \
44
THREAD_ANNOTATION_ATTRIBUTE_(release_capability(__VA_ARGS__))
45
46
#define RELEASE_SHARED(...) \
47
THREAD_ANNOTATION_ATTRIBUTE_(release_shared_capability(__VA_ARGS__))
48
49
#define TRY_ACQUIRE(...) \
50
THREAD_ANNOTATION_ATTRIBUTE_(try_acquire_capability(__VA_ARGS__))
51
52
#define TRY_ACQUIRE_SHARED(...) \
53
THREAD_ANNOTATION_ATTRIBUTE_(try_acquire_shared_capability(__VA_ARGS__))
54
55
#define EXCLUDES(...) THREAD_ANNOTATION_ATTRIBUTE_(locks_excluded(__VA_ARGS__))
56
57
#define ASSERT_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE_(assert_capability(x))
58
59
#define ASSERT_SHARED_CAPABILITY(x) \
60
THREAD_ANNOTATION_ATTRIBUTE_(assert_shared_capability(x))
61
62
#define RETURN_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE_(lock_returned(x))
63
64
#define NO_THREAD_SAFETY_ANALYSIS \
65
THREAD_ANNOTATION_ATTRIBUTE_(no_thread_safety_analysis)
66
67
namespace
benchmark {
68
69
typedef
std::condition_variable Condition;
70
71
// NOTE: Wrappers for std::mutex and std::unique_lock are provided so that
72
// we can annotate them with thread safety attributes and use the
73
// -Wthread-safety warning with clang. The standard library types cannot be
74
// used directly because they do not provide the required annotations.
75
class
CAPABILITY(
"mutex"
) Mutex {
76
public
:
77
Mutex() {}
78
79
void
lock() ACQUIRE() { mut_.lock(); }
80
void
unlock() RELEASE() { mut_.unlock(); }
81
std::mutex& native_handle() {
return
mut_; }
82
83
private
:
84
std::mutex mut_;
85
};
86
87
class
SCOPED_CAPABILITY MutexLock {
88
typedef
std::unique_lock<std::mutex> MutexLockImp;
89
90
public
:
91
MutexLock(Mutex& m) ACQUIRE(m) : ml_(m.native_handle()) {}
92
~MutexLock() RELEASE() {}
93
MutexLockImp& native_handle() {
return
ml_; }
94
95
private
:
96
MutexLockImp ml_;
97
};
98
99
class
Barrier {
100
public
:
101
Barrier(
int
num_threads) : running_threads_(num_threads) {}
102
103
// Called by each thread
104
bool
wait() EXCLUDES(lock_) {
105
bool
last_thread =
false
;
106
{
107
MutexLock
ml(lock_);
108
last_thread = createBarrier(ml);
109
}
110
if
(last_thread) phase_condition_.notify_all();
111
return
last_thread;
112
}
113
114
void
removeThread() EXCLUDES(lock_) {
115
MutexLock
ml(lock_);
116
--running_threads_;
117
if
(entered_ != 0) phase_condition_.notify_all();
118
}
119
120
private
:
121
Mutex lock_;
122
Condition phase_condition_;
123
int
running_threads_;
124
125
// State for barrier management
126
int
phase_number_ = 0;
127
int
entered_ = 0;
// Number of threads that have entered this barrier
128
129
// Enter the barrier and wait until all other threads have also
130
// entered the barrier. Returns iff this is the last thread to
131
// enter the barrier.
132
bool
createBarrier(
MutexLock
& ml) REQUIRES(lock_) {
133
BM_CHECK_LT(entered_, running_threads_);
134
entered_++;
135
if
(entered_ < running_threads_) {
136
// Wait for all threads to enter
137
int
phase_number_cp = phase_number_;
138
auto
cb = [
this
, phase_number_cp]() {
139
return
this->phase_number_ > phase_number_cp ||
140
entered_ == running_threads_;
// A thread has aborted in error
141
};
142
phase_condition_.wait(ml.native_handle(), cb);
143
if
(phase_number_ > phase_number_cp)
return
false
;
144
// else (running_threads_ == entered_) and we are the last thread.
145
}
146
// Last thread has reached the barrier
147
phase_number_++;
148
entered_ = 0;
149
return
true
;
150
}
151
};
152
153
}
// end namespace benchmark
154
155
#endif
// BENCHMARK_MUTEX_H_
benchmark::MutexLock
Definition
mutex.h:87
src
mutex.h
Generated by
1.17.0