|
|
|||
File indexing completed on 2026-05-10 08:42:57
0001 //===-- Predicate.h ---------------------------------------------*- C++ -*-===// 0002 // 0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 0004 // See https://llvm.org/LICENSE.txt for license information. 0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 0006 // 0007 //===----------------------------------------------------------------------===// 0008 0009 #ifndef LLDB_UTILITY_PREDICATE_H 0010 #define LLDB_UTILITY_PREDICATE_H 0011 0012 #include <cstdint> 0013 #include <ctime> 0014 0015 #include <condition_variable> 0016 #include <mutex> 0017 #include <optional> 0018 0019 #include "lldb/Utility/Timeout.h" 0020 #include "lldb/lldb-defines.h" 0021 0022 //#define DB_PTHREAD_LOG_EVENTS 0023 0024 /// Enumerations for broadcasting. 0025 namespace lldb_private { 0026 0027 enum PredicateBroadcastType { 0028 eBroadcastNever, ///< No broadcast will be sent when the value is modified. 0029 eBroadcastAlways, ///< Always send a broadcast when the value is modified. 0030 eBroadcastOnChange ///< Only broadcast if the value changes when the value is 0031 /// modified. 0032 }; 0033 0034 /// \class Predicate Predicate.h "lldb/Utility/Predicate.h" 0035 /// A C++ wrapper class for providing threaded access to a value of 0036 /// type T. 0037 /// 0038 /// A templatized class that provides multi-threaded access to a value 0039 /// of type T. Threads can efficiently wait for bits within T to be set 0040 /// or reset, or wait for T to be set to be equal/not equal to a 0041 /// specified values. 0042 template <class T> class Predicate { 0043 public: 0044 /// Default constructor. 0045 /// 0046 /// Initializes the mutex, condition and value with their default 0047 /// constructors. 0048 Predicate() : m_value() {} 0049 0050 /// Construct with initial T value \a initial_value. 0051 /// 0052 /// Initializes the mutex and condition with their default 0053 /// constructors, and initializes the value with \a initial_value. 0054 /// 0055 /// \param[in] initial_value 0056 /// The initial value for our T object. 0057 Predicate(T initial_value) : m_value(initial_value) {} 0058 0059 /// Destructor. 0060 /// 0061 /// Destroy the condition, mutex, and T objects. 0062 ~Predicate() = default; 0063 0064 /// Value get accessor. 0065 /// 0066 /// Copies the current \a m_value in a thread safe manor and returns 0067 /// the copied value. 0068 /// 0069 /// \return 0070 /// A copy of the current value. 0071 T GetValue() const { 0072 std::lock_guard<std::mutex> guard(m_mutex); 0073 T value = m_value; 0074 return value; 0075 } 0076 0077 /// Value set accessor. 0078 /// 0079 /// Set the contained \a m_value to \a new_value in a thread safe 0080 /// way and broadcast if needed. 0081 /// 0082 /// \param[in] value 0083 /// The new value to set. 0084 /// 0085 /// \param[in] broadcast_type 0086 /// A value indicating when and if to broadcast. See the 0087 /// PredicateBroadcastType enumeration for details. 0088 /// 0089 /// \see Predicate::Broadcast() 0090 void SetValue(T value, PredicateBroadcastType broadcast_type) { 0091 std::lock_guard<std::mutex> guard(m_mutex); 0092 #ifdef DB_PTHREAD_LOG_EVENTS 0093 printf("%s (value = 0x%8.8x, broadcast_type = %i)\n", __FUNCTION__, value, 0094 broadcast_type); 0095 #endif 0096 const T old_value = m_value; 0097 m_value = value; 0098 0099 Broadcast(old_value, broadcast_type); 0100 } 0101 0102 /// Wait for Cond(m_value) to be true. 0103 /// 0104 /// Waits in a thread safe way for Cond(m_value) to be true. If Cond(m_value) 0105 /// is already true, this function will return without waiting. 0106 /// 0107 /// It is possible for the value to be changed between the time the value is 0108 /// set and the time the waiting thread wakes up. If the value no longer 0109 /// satisfies the condition when the waiting thread wakes up, it will go back 0110 /// into a wait state. It may be necessary for the calling code to use 0111 /// additional thread synchronization methods to detect transitory states. 0112 /// 0113 /// \param[in] Cond 0114 /// The condition we want \a m_value satisfy. 0115 /// 0116 /// \param[in] timeout 0117 /// How long to wait for the condition to hold. 0118 /// 0119 /// \return 0120 /// m_value if Cond(m_value) is true, std::nullopt otherwise (timeout 0121 /// occurred). 0122 template <typename C> 0123 std::optional<T> WaitFor(C Cond, const Timeout<std::micro> &timeout) { 0124 std::unique_lock<std::mutex> lock(m_mutex); 0125 auto RealCond = [&] { return Cond(m_value); }; 0126 if (!timeout) { 0127 m_condition.wait(lock, RealCond); 0128 return m_value; 0129 } 0130 if (m_condition.wait_for(lock, *timeout, RealCond)) 0131 return m_value; 0132 return std::nullopt; 0133 } 0134 /// Wait for \a m_value to be equal to \a value. 0135 /// 0136 /// Waits in a thread safe way for \a m_value to be equal to \a 0137 /// value. If \a m_value is already equal to \a value, this 0138 /// function will return without waiting. 0139 /// 0140 /// It is possible for the value to be changed between the time 0141 /// the value is set and the time the waiting thread wakes up. 0142 /// If the value no longer matches the requested value when the 0143 /// waiting thread wakes up, it will go back into a wait state. It 0144 /// may be necessary for the calling code to use additional thread 0145 /// synchronization methods to detect transitory states. 0146 /// 0147 /// \param[in] value 0148 /// The value we want \a m_value to be equal to. 0149 /// 0150 /// \param[in] timeout 0151 /// How long to wait for the condition to hold. 0152 /// 0153 /// \return 0154 /// true if the \a m_value is equal to \a value, false otherwise (timeout 0155 /// occurred). 0156 bool WaitForValueEqualTo(T value, 0157 const Timeout<std::micro> &timeout = std::nullopt) { 0158 return WaitFor([&value](T current) { return value == current; }, timeout) != 0159 std::nullopt; 0160 } 0161 0162 /// Wait for \a m_value to not be equal to \a value. 0163 /// 0164 /// Waits in a thread safe way for \a m_value to not be equal to \a 0165 /// value. If \a m_value is already not equal to \a value, this 0166 /// function will return without waiting. 0167 /// 0168 /// It is possible for the value to be changed between the time 0169 /// the value is set and the time the waiting thread wakes up. 0170 /// If the value is equal to the test value when the waiting thread 0171 /// wakes up, it will go back into a wait state. It may be 0172 /// necessary for the calling code to use additional thread 0173 /// synchronization methods to detect transitory states. 0174 /// 0175 /// \param[in] value 0176 /// The value we want \a m_value to not be equal to. 0177 /// 0178 /// \param[in] timeout 0179 /// How long to wait for the condition to hold. 0180 /// 0181 /// \return 0182 /// m_value if m_value != value, std::nullopt otherwise (timeout 0183 /// occurred). 0184 std::optional<T> 0185 WaitForValueNotEqualTo(T value, 0186 const Timeout<std::micro> &timeout = std::nullopt) { 0187 return WaitFor([&value](T current) { return value != current; }, timeout); 0188 } 0189 0190 protected: 0191 // pthread condition and mutex variable to control access and allow blocking 0192 // between the main thread and the spotlight index thread. 0193 T m_value; ///< The templatized value T that we are protecting access to 0194 mutable std::mutex m_mutex; ///< The mutex to use when accessing the data 0195 std::condition_variable m_condition; ///< The pthread condition variable to 0196 /// use for signaling that data available 0197 /// or changed. 0198 0199 private: 0200 /// Broadcast if needed. 0201 /// 0202 /// Check to see if we need to broadcast to our condition variable 0203 /// depending on the \a old_value and on the \a broadcast_type. 0204 /// 0205 /// If \a broadcast_type is eBroadcastNever, no broadcast will be 0206 /// sent. 0207 /// 0208 /// If \a broadcast_type is eBroadcastAlways, the condition variable 0209 /// will always be broadcast. 0210 /// 0211 /// If \a broadcast_type is eBroadcastOnChange, the condition 0212 /// variable be broadcast if the owned value changes. 0213 void Broadcast(T old_value, PredicateBroadcastType broadcast_type) { 0214 bool broadcast = 0215 (broadcast_type == eBroadcastAlways) || 0216 ((broadcast_type == eBroadcastOnChange) && old_value != m_value); 0217 #ifdef DB_PTHREAD_LOG_EVENTS 0218 printf("%s (old_value = 0x%8.8x, broadcast_type = %i) m_value = 0x%8.8x, " 0219 "broadcast = %u\n", 0220 __FUNCTION__, old_value, broadcast_type, m_value, broadcast); 0221 #endif 0222 if (broadcast) 0223 m_condition.notify_all(); 0224 } 0225 0226 Predicate(const Predicate &) = delete; 0227 const Predicate &operator=(const Predicate &) = delete; 0228 }; 0229 0230 } // namespace lldb_private 0231 0232 #endif // LLDB_UTILITY_PREDICATE_H
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|