20
20
21
21
// Other libraries and framework includes
22
22
// Project includes
23
+ #include " lldb/Utility/Timeout.h"
23
24
#include " lldb/lldb-defines.h"
24
25
25
26
// #define DB_PTHREAD_LOG_EVENTS
@@ -117,6 +118,40 @@ template <class T> class Predicate {
117
118
Broadcast (old_value, broadcast_type);
118
119
}
119
120
121
+ // ------------------------------------------------------------------
122
+ // / Wait for Cond(m_value) to be true.
123
+ // /
124
+ // / Waits in a thread safe way for Cond(m_value) to be true. If Cond(m_value)
125
+ // / is already true, this function will return without waiting.
126
+ // /
127
+ // / It is possible for the value to be changed between the time the value is
128
+ // / set and the time the waiting thread wakes up. If the value no longer
129
+ // / satisfies the condition when the waiting thread wakes up, it will go back
130
+ // / into a wait state. It may be necessary for the calling code to use
131
+ // / additional thread synchronization methods to detect transitory states.
132
+ // /
133
+ // / @param[in] Cond
134
+ // / The condition we want \a m_value satisfy.
135
+ // /
136
+ // / @param[in] timeout
137
+ // / How long to wait for the condition to hold.
138
+ // /
139
+ // / @return
140
+ // / @li m_value if Cond(m_value) is true.
141
+ // / @li None otherwise (timeout occurred).
142
+ // ------------------------------------------------------------------
143
+ template <typename C>
144
+ llvm::Optional<T> WaitFor (C Cond, const Timeout<std::micro> &timeout) {
145
+ std::unique_lock<std::mutex> lock (m_mutex);
146
+ auto RealCond = [&] { return Cond (m_value); };
147
+ if (!timeout) {
148
+ m_condition.wait (lock, RealCond);
149
+ return m_value;
150
+ }
151
+ if (m_condition.wait_for (lock, *timeout, RealCond))
152
+ return m_value;
153
+ return llvm::None;
154
+ }
120
155
// ------------------------------------------------------------------
121
156
// / Wait for \a m_value to be equal to \a value.
122
157
// /
@@ -134,38 +169,17 @@ template <class T> class Predicate {
134
169
// / @param[in] value
135
170
// / The value we want \a m_value to be equal to.
136
171
// /
137
- // / @param[in] abstime
138
- // / If non-nullptr, the absolute time at which we should stop
139
- // / waiting, else wait an infinite amount of time.
172
+ // / @param[in] timeout
173
+ // / How long to wait for the condition to hold.
140
174
// /
141
175
// / @return
142
176
// / @li \b true if the \a m_value is equal to \a value
143
177
// / @li \b false otherwise (timeout occurred)
144
178
// ------------------------------------------------------------------
145
- bool WaitForValueEqualTo (T value, const std::chrono::microseconds &timeout =
146
- std::chrono::microseconds (0 )) {
147
- // pthread_cond_timedwait() or pthread_cond_wait() will atomically unlock
148
- // the mutex and wait for the condition to be set. When either function
149
- // returns, they will re-lock the mutex. We use an auto lock/unlock class
150
- // (std::lock_guard) to allow us to return at any point in this function
151
- // and not have to worry about unlocking the mutex.
152
- std::unique_lock<std::mutex> lock (m_mutex);
153
-
154
- #ifdef DB_PTHREAD_LOG_EVENTS
155
- printf (" %s (value = 0x%8.8x, timeout = %llu), m_value = 0x%8.8x\n " ,
156
- __FUNCTION__, value, timeout.count (), m_value);
157
- #endif
158
- while (m_value != value) {
159
- if (timeout == std::chrono::microseconds (0 )) {
160
- m_condition.wait (lock);
161
- } else {
162
- std::cv_status result = m_condition.wait_for (lock, timeout);
163
- if (result == std::cv_status::timeout)
164
- break ;
165
- }
166
- }
167
-
168
- return m_value == value;
179
+ bool WaitForValueEqualTo (T value,
180
+ const Timeout<std::micro> &timeout = llvm::None) {
181
+ return WaitFor ([&value](T current) { return value == current; }, timeout) !=
182
+ llvm::None;
169
183
}
170
184
171
185
// ------------------------------------------------------------------
@@ -185,45 +199,17 @@ template <class T> class Predicate {
185
199
// / @param[in] value
186
200
// / The value we want \a m_value to not be equal to.
187
201
// /
188
- // / @param[out] new_value
189
- // / The new value if \b true is returned.
190
- // /
191
- // / @param[in] abstime
192
- // / If non-nullptr, the absolute time at which we should stop
193
- // / waiting, else wait an infinite amount of time.
202
+ // / @param[in] timeout
203
+ // / How long to wait for the condition to hold.
194
204
// /
195
205
// / @return
196
- // / @li \b true if the \a m_value is equal to \a value
197
- // / @li \b false otherwise
206
+ // / @li m_value if m_value != value
207
+ // / @li None otherwise (timeout occurred).
198
208
// ------------------------------------------------------------------
199
- bool WaitForValueNotEqualTo (
200
- T value, T &new_value,
201
- const std::chrono::microseconds &timeout = std::chrono::microseconds(0 )) {
202
- // pthread_cond_timedwait() or pthread_cond_wait() will atomically unlock
203
- // the mutex and wait for the condition to be set. When either function
204
- // returns, they will re-lock the mutex. We use an auto lock/unlock class
205
- // (std::lock_guard) to allow us to return at any point in this function
206
- // and not have to worry about unlocking the mutex.
207
- std::unique_lock<std::mutex> lock (m_mutex);
208
- #ifdef DB_PTHREAD_LOG_EVENTS
209
- printf (" %s (value = 0x%8.8x, timeout = %llu), m_value = 0x%8.8x\n " ,
210
- __FUNCTION__, value, timeout.count (), m_value);
211
- #endif
212
- while (m_value == value) {
213
- if (timeout == std::chrono::microseconds (0 )) {
214
- m_condition.wait (lock);
215
- } else {
216
- std::cv_status result = m_condition.wait_for (lock, timeout);
217
- if (result == std::cv_status::timeout)
218
- break ;
219
- }
220
- }
221
-
222
- if (m_value != value) {
223
- new_value = m_value;
224
- return true ;
225
- }
226
- return false ;
209
+ llvm::Optional<T>
210
+ WaitForValueNotEqualTo (T value,
211
+ const Timeout<std::micro> &timeout = llvm::None) {
212
+ return WaitFor ([&value](T current) { return value != current; }, timeout);
227
213
}
228
214
229
215
protected:
0 commit comments