1 //===-- Predicate.h ---------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef liblldb_Predicate_h_ 11 #define liblldb_Predicate_h_ 12 #if defined(__cplusplus) 13 14 #include "lldb/lldb-defines.h" 15 #include "lldb/Host/Mutex.h" 16 #include "lldb/Host/Condition.h" 17 #include <stdint.h> 18 #include <time.h> 19 20 //#define DB_PTHREAD_LOG_EVENTS 21 22 //---------------------------------------------------------------------- 23 /// Enumerations for broadcasting. 24 //---------------------------------------------------------------------- 25 namespace lldb_private { 26 27 typedef enum 28 { 29 eBroadcastNever, ///< No broadcast will be sent when the value is modified. 30 eBroadcastAlways, ///< Always send a broadcast when the value is modified. 31 eBroadcastOnChange ///< Only broadcast if the value changes when the value is modified. 32 33 } PredicateBroadcastType; 34 35 //---------------------------------------------------------------------- 36 /// @class Predicate Predicate.h "lldb/Host/Predicate.h" 37 /// @brief A C++ wrapper class for providing threaded access to a value 38 /// of type T. 39 /// 40 /// A templatized class that provides multi-threaded access to a value 41 /// of type T. Threads can efficiently wait for bits within T to be set 42 /// or reset, or wait for T to be set to be equal/not equal to a 43 /// specified values. 44 //---------------------------------------------------------------------- 45 template <class T> 46 class Predicate 47 { 48 public: 49 50 //------------------------------------------------------------------ 51 /// Default constructor. 52 /// 53 /// Initializes the mutex, condition and value with their default 54 /// constructors. 55 //------------------------------------------------------------------ Predicate()56 Predicate () : 57 m_value(), 58 m_mutex(), 59 m_condition() 60 { 61 } 62 63 //------------------------------------------------------------------ 64 /// Construct with initial T value \a initial_value. 65 /// 66 /// Initializes the mutex and condition with their default 67 /// constructors, and initializes the value with \a initial_value. 68 /// 69 /// @param[in] initial_value 70 /// The initial value for our T object. 71 //------------------------------------------------------------------ Predicate(T initial_value)72 Predicate (T initial_value) : 73 m_value(initial_value), 74 m_mutex(), 75 m_condition() 76 { 77 } 78 79 //------------------------------------------------------------------ 80 /// Destructor. 81 /// 82 /// Destroy the condition, mutex, and T objects. 83 //------------------------------------------------------------------ ~Predicate()84 ~Predicate () 85 { 86 } 87 88 89 //------------------------------------------------------------------ 90 /// Value get accessor. 91 /// 92 /// Copies the current \a m_value in a thread safe manor and returns 93 /// the copied value. 94 /// 95 /// @return 96 /// A copy of the current value. 97 //------------------------------------------------------------------ 98 T GetValue()99 GetValue () const 100 { 101 Mutex::Locker locker(m_mutex); 102 T value = m_value; 103 return value; 104 } 105 106 //------------------------------------------------------------------ 107 /// Value set accessor. 108 /// 109 /// Set the contained \a m_value to \a new_value in a thread safe 110 /// way and broadcast if needed. 111 /// 112 /// @param[in] value 113 /// The new value to set. 114 /// 115 /// @param[in] broadcast_type 116 /// A value indicating when and if to broadcast. See the 117 /// PredicateBroadcastType enumeration for details. 118 /// 119 /// @see Predicate::Broadcast() 120 //------------------------------------------------------------------ 121 void SetValue(T value,PredicateBroadcastType broadcast_type)122 SetValue (T value, PredicateBroadcastType broadcast_type) 123 { 124 Mutex::Locker locker(m_mutex); 125 #ifdef DB_PTHREAD_LOG_EVENTS 126 printf("%s (value = 0x%8.8x, broadcast_type = %i)\n", __FUNCTION__, value, broadcast_type); 127 #endif 128 const T old_value = m_value; 129 m_value = value; 130 131 Broadcast(old_value, broadcast_type); 132 } 133 134 //------------------------------------------------------------------ 135 /// Set some bits in \a m_value. 136 /// 137 /// Logically set the bits \a bits in the contained \a m_value in a 138 /// thread safe way and broadcast if needed. 139 /// 140 /// @param[in] bits 141 /// The bits to set in \a m_value. 142 /// 143 /// @param[in] broadcast_type 144 /// A value indicating when and if to broadcast. See the 145 /// PredicateBroadcastType enumeration for details. 146 /// 147 /// @see Predicate::Broadcast() 148 //------------------------------------------------------------------ 149 void SetValueBits(T bits,PredicateBroadcastType broadcast_type)150 SetValueBits (T bits, PredicateBroadcastType broadcast_type) 151 { 152 Mutex::Locker locker(m_mutex); 153 #ifdef DB_PTHREAD_LOG_EVENTS 154 printf("%s (bits = 0x%8.8x, broadcast_type = %i)\n", __FUNCTION__, bits, broadcast_type); 155 #endif 156 const T old_value = m_value; 157 m_value |= bits; 158 159 Broadcast(old_value, broadcast_type); 160 } 161 162 //------------------------------------------------------------------ 163 /// Reset some bits in \a m_value. 164 /// 165 /// Logically reset (clear) the bits \a bits in the contained 166 /// \a m_value in a thread safe way and broadcast if needed. 167 /// 168 /// @param[in] bits 169 /// The bits to clear in \a m_value. 170 /// 171 /// @param[in] broadcast_type 172 /// A value indicating when and if to broadcast. See the 173 /// PredicateBroadcastType enumeration for details. 174 /// 175 /// @see Predicate::Broadcast() 176 //------------------------------------------------------------------ 177 void ResetValueBits(T bits,PredicateBroadcastType broadcast_type)178 ResetValueBits (T bits, PredicateBroadcastType broadcast_type) 179 { 180 Mutex::Locker locker(m_mutex); 181 #ifdef DB_PTHREAD_LOG_EVENTS 182 printf("%s (bits = 0x%8.8x, broadcast_type = %i)\n", __FUNCTION__, bits, broadcast_type); 183 #endif 184 const T old_value = m_value; 185 m_value &= ~bits; 186 187 Broadcast(old_value, broadcast_type); 188 } 189 190 //------------------------------------------------------------------ 191 /// Wait for bits to be set in \a m_value. 192 /// 193 /// Waits in a thread safe way for any bits in \a bits to get 194 /// logically set in \a m_value. If any bits are already set in 195 /// \a m_value, this function will return without waiting. 196 /// 197 /// It is possible for the value to be changed between the time 198 /// the bits are set and the time the waiting thread wakes up. 199 /// If the bits are no longer set when the waiting thread wakes 200 /// up, it will go back into a wait state. It may be necessary 201 /// for the calling code to use additional thread synchronization 202 /// methods to detect transitory states. 203 /// 204 /// @param[in] bits 205 /// The bits we are waiting to be set in \a m_value. 206 /// 207 /// @param[in] abstime 208 /// If non-NULL, the absolute time at which we should stop 209 /// waiting, else wait an infinite amount of time. 210 /// 211 /// @return 212 /// Any bits of the requested bits that actually were set within 213 /// the time specified. Zero if a timeout or unrecoverable error 214 /// occurred. 215 //------------------------------------------------------------------ 216 T 217 WaitForSetValueBits (T bits, const TimeValue *abstime = NULL) 218 { 219 int err = 0; 220 // pthread_cond_timedwait() or pthread_cond_wait() will atomically 221 // unlock the mutex and wait for the condition to be set. When either 222 // function returns, they will re-lock the mutex. We use an auto lock/unlock 223 // class (Mutex::Locker) to allow us to return at any point in this 224 // function and not have to worry about unlocking the mutex. 225 Mutex::Locker locker(m_mutex); 226 #ifdef DB_PTHREAD_LOG_EVENTS 227 printf("%s (bits = 0x%8.8x, abstime = %p), m_value = 0x%8.8x\n", __FUNCTION__, bits, abstime, m_value); 228 #endif 229 while (err == 0 && ((m_value & bits) == 0)) 230 { 231 err = m_condition.Wait (m_mutex, abstime); 232 } 233 #ifdef DB_PTHREAD_LOG_EVENTS 234 printf("%s (bits = 0x%8.8x), m_value = 0x%8.8x, returning 0x%8.8x\n", __FUNCTION__, bits, m_value, m_value & bits); 235 #endif 236 237 return m_value & bits; 238 } 239 240 //------------------------------------------------------------------ 241 /// Wait for bits to be reset in \a m_value. 242 /// 243 /// Waits in a thread safe way for any bits in \a bits to get 244 /// logically reset in \a m_value. If all bits are already reset in 245 /// \a m_value, this function will return without waiting. 246 /// 247 /// It is possible for the value to be changed between the time 248 /// the bits are reset and the time the waiting thread wakes up. 249 /// If the bits are no set when the waiting thread wakes up, it will 250 /// go back into a wait state. It may be necessary for the calling 251 /// code to use additional thread synchronization methods to detect 252 /// transitory states. 253 /// 254 /// @param[in] bits 255 /// The bits we are waiting to be reset in \a m_value. 256 /// 257 /// @param[in] abstime 258 /// If non-NULL, the absolute time at which we should stop 259 /// waiting, else wait an infinite amount of time. 260 /// 261 /// @return 262 /// Zero on successful waits, or non-zero if a timeout or 263 /// unrecoverable error occurs. 264 //------------------------------------------------------------------ 265 T 266 WaitForResetValueBits (T bits, const TimeValue *abstime = NULL) 267 { 268 int err = 0; 269 270 // pthread_cond_timedwait() or pthread_cond_wait() will atomically 271 // unlock the mutex and wait for the condition to be set. When either 272 // function returns, they will re-lock the mutex. We use an auto lock/unlock 273 // class (Mutex::Locker) to allow us to return at any point in this 274 // function and not have to worry about unlocking the mutex. 275 Mutex::Locker locker(m_mutex); 276 277 #ifdef DB_PTHREAD_LOG_EVENTS 278 printf("%s (bits = 0x%8.8x, abstime = %p), m_value = 0x%8.8x\n", __FUNCTION__, bits, abstime, m_value); 279 #endif 280 while (err == 0 && ((m_value & bits) != 0)) 281 { 282 err = m_condition.Wait (m_mutex, abstime); 283 } 284 285 #ifdef DB_PTHREAD_LOG_EVENTS 286 printf("%s (bits = 0x%8.8x), m_value = 0x%8.8x, returning 0x%8.8x\n", __FUNCTION__, bits, m_value, m_value & bits); 287 #endif 288 return m_value & bits; 289 } 290 291 //------------------------------------------------------------------ 292 /// Wait for \a m_value to be equal to \a value. 293 /// 294 /// Waits in a thread safe way for \a m_value to be equal to \a 295 /// value. If \a m_value is already equal to \a value, this 296 /// function will return without waiting. 297 /// 298 /// It is possible for the value to be changed between the time 299 /// the value is set and the time the waiting thread wakes up. 300 /// If the value no longer matches the requested value when the 301 /// waiting thread wakes up, it will go back into a wait state. It 302 /// may be necessary for the calling code to use additional thread 303 /// synchronization methods to detect transitory states. 304 /// 305 /// @param[in] value 306 /// The value we want \a m_value to be equal to. 307 /// 308 /// @param[in] abstime 309 /// If non-NULL, the absolute time at which we should stop 310 /// waiting, else wait an infinite amount of time. 311 /// 312 /// @param[out] timed_out 313 /// If not null, set to true if we return because of a time out, 314 /// and false if the value was set. 315 /// 316 /// @return 317 /// @li \b true if the \a m_value is equal to \a value 318 /// @li \b false otherwise 319 //------------------------------------------------------------------ 320 bool 321 WaitForValueEqualTo (T value, const TimeValue *abstime = NULL, bool *timed_out = NULL) 322 { 323 int err = 0; 324 // pthread_cond_timedwait() or pthread_cond_wait() will atomically 325 // unlock the mutex and wait for the condition to be set. When either 326 // function returns, they will re-lock the mutex. We use an auto lock/unlock 327 // class (Mutex::Locker) to allow us to return at any point in this 328 // function and not have to worry about unlocking the mutex. 329 Mutex::Locker locker(m_mutex); 330 331 #ifdef DB_PTHREAD_LOG_EVENTS 332 printf("%s (value = 0x%8.8x, abstime = %p), m_value = 0x%8.8x\n", __FUNCTION__, value, abstime, m_value); 333 #endif 334 if (timed_out) 335 *timed_out = false; 336 337 while (err == 0 && m_value != value) 338 { 339 err = m_condition.Wait (m_mutex, abstime, timed_out); 340 } 341 342 return m_value == value; 343 } 344 345 //------------------------------------------------------------------ 346 /// Wait for \a m_value to be equal to \a value and then set it to 347 /// a new value. 348 /// 349 /// Waits in a thread safe way for \a m_value to be equal to \a 350 /// value and then sets \a m_value to \a new_value. If \a m_value 351 /// is already equal to \a value, this function will immediately 352 /// set \a m_value to \a new_value and return without waiting. 353 /// 354 /// It is possible for the value to be changed between the time 355 /// the value is set and the time the waiting thread wakes up. 356 /// If the value no longer matches the requested value when the 357 /// waiting thread wakes up, it will go back into a wait state. It 358 /// may be necessary for the calling code to use additional thread 359 /// synchronization methods to detect transitory states. 360 /// 361 /// @param[in] value 362 /// The value we want \a m_value to be equal to. 363 /// 364 /// @param[in] new_value 365 /// The value to which \a m_value will be set if \b true is 366 /// returned. 367 /// 368 /// @param[in] abstime 369 /// If non-NULL, the absolute time at which we should stop 370 /// waiting, else wait an infinite amount of time. 371 /// 372 /// @param[out] timed_out 373 /// If not null, set to true if we return because of a time out, 374 /// and false if the value was set. 375 /// 376 /// @return 377 /// @li \b true if the \a m_value became equal to \a value 378 /// @li \b false otherwise 379 //------------------------------------------------------------------ 380 bool 381 WaitForValueEqualToAndSetValueTo (T wait_value, T new_value, const TimeValue *abstime = NULL, bool *timed_out = NULL) 382 { 383 int err = 0; 384 // pthread_cond_timedwait() or pthread_cond_wait() will atomically 385 // unlock the mutex and wait for the condition to be set. When either 386 // function returns, they will re-lock the mutex. We use an auto lock/unlock 387 // class (Mutex::Locker) to allow us to return at any point in this 388 // function and not have to worry about unlocking the mutex. 389 Mutex::Locker locker(m_mutex); 390 391 #ifdef DB_PTHREAD_LOG_EVENTS 392 printf("%s (wait_value = 0x%8.8x, new_value = 0x%8.8x, abstime = %p), m_value = 0x%8.8x\n", __FUNCTION__, wait_value, new_value, abstime, m_value); 393 #endif 394 if (timed_out) 395 *timed_out = false; 396 397 while (err == 0 && m_value != wait_value) 398 { 399 err = m_condition.Wait (m_mutex, abstime, timed_out); 400 } 401 402 if (m_value == wait_value) 403 { 404 m_value = new_value; 405 return true; 406 } 407 408 return false; 409 } 410 411 412 //------------------------------------------------------------------ 413 /// Wait for \a m_value to not be equal to \a value. 414 /// 415 /// Waits in a thread safe way for \a m_value to not be equal to \a 416 /// value. If \a m_value is already not equal to \a value, this 417 /// function will return without waiting. 418 /// 419 /// It is possible for the value to be changed between the time 420 /// the value is set and the time the waiting thread wakes up. 421 /// If the value is equal to the test value when the waiting thread 422 /// wakes up, it will go back into a wait state. It may be 423 /// necessary for the calling code to use additional thread 424 /// synchronization methods to detect transitory states. 425 /// 426 /// @param[in] value 427 /// The value we want \a m_value to not be equal to. 428 /// 429 /// @param[out] new_value 430 /// The new value if \b true is returned. 431 /// 432 /// @param[in] abstime 433 /// If non-NULL, the absolute time at which we should stop 434 /// waiting, else wait an infinite amount of time. 435 /// 436 /// @return 437 /// @li \b true if the \a m_value is equal to \a value 438 /// @li \b false otherwise 439 //------------------------------------------------------------------ 440 bool 441 WaitForValueNotEqualTo (T value, T &new_value, const TimeValue *abstime = NULL) 442 { 443 int err = 0; 444 // pthread_cond_timedwait() or pthread_cond_wait() will atomically 445 // unlock the mutex and wait for the condition to be set. When either 446 // function returns, they will re-lock the mutex. We use an auto lock/unlock 447 // class (Mutex::Locker) to allow us to return at any point in this 448 // function and not have to worry about unlocking the mutex. 449 Mutex::Locker locker(m_mutex); 450 #ifdef DB_PTHREAD_LOG_EVENTS 451 printf("%s (value = 0x%8.8x, abstime = %p), m_value = 0x%8.8x\n", __FUNCTION__, value, abstime, m_value); 452 #endif 453 while (err == 0 && m_value == value) 454 { 455 err = m_condition.Wait (m_mutex, abstime); 456 } 457 458 if (m_value != value) 459 { 460 new_value = m_value; 461 return true; 462 } 463 return false; 464 } 465 466 protected: 467 //---------------------------------------------------------------------- 468 // pthread condition and mutex variable to control access and allow 469 // blocking between the main thread and the spotlight index thread. 470 //---------------------------------------------------------------------- 471 T m_value; ///< The templatized value T that we are protecting access to 472 mutable Mutex m_mutex; ///< The mutex to use when accessing the data 473 Condition m_condition; ///< The pthread condition variable to use for signaling that data available or changed. 474 475 private: 476 477 //------------------------------------------------------------------ 478 /// Broadcast if needed. 479 /// 480 /// Check to see if we need to broadcast to our condition variable 481 /// depending on the \a old_value and on the \a broadcast_type. 482 /// 483 /// If \a broadcast_type is eBroadcastNever, no broadcast will be 484 /// sent. 485 /// 486 /// If \a broadcast_type is eBroadcastAlways, the condition variable 487 /// will always be broadcast. 488 /// 489 /// If \a broadcast_type is eBroadcastOnChange, the condition 490 /// variable be broadcast if the owned value changes. 491 //------------------------------------------------------------------ 492 void Broadcast(T old_value,PredicateBroadcastType broadcast_type)493 Broadcast (T old_value, PredicateBroadcastType broadcast_type) 494 { 495 bool broadcast = (broadcast_type == eBroadcastAlways) || ((broadcast_type == eBroadcastOnChange) && old_value != m_value); 496 #ifdef DB_PTHREAD_LOG_EVENTS 497 printf("%s (old_value = 0x%8.8x, broadcast_type = %i) m_value = 0x%8.8x, broadcast = %u\n", __FUNCTION__, old_value, broadcast_type, m_value, broadcast); 498 #endif 499 if (broadcast) 500 m_condition.Broadcast(); 501 } 502 503 504 DISALLOW_COPY_AND_ASSIGN(Predicate); 505 }; 506 507 } // namespace lldb_private 508 509 #endif // #if defined(__cplusplus) 510 #endif // #ifndef liblldb_Predicate_h_ 511