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