Home | History | Annotate | Download | only in Host
      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 //----------------------------------------------------------------------
     24 namespace lldb_private {
     25 
     26 typedef 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 //----------------------------------------------------------------------
     44 template <class T>
     45 class Predicate
     46 {
     47 public:
     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     /// It is possible for the value to be changed between the time
    197     /// the bits are set and the time the waiting thread wakes up.
    198     /// If the bits are no longer set when the waiting thread wakes
    199     /// up, it will go back into a wait state.  It may be necessary
    200     /// for the calling code to use additional thread synchronization
    201     /// methods to detect transitory states.
    202     ///
    203     /// @param[in] bits
    204     ///     The bits we are waiting to be set in \a m_value.
    205     ///
    206     /// @param[in] abstime
    207     ///     If non-NULL, the absolute time at which we should stop
    208     ///     waiting, else wait an infinite amount of time.
    209     ///
    210     /// @return
    211     ///     Any bits of the requested bits that actually were set within
    212     ///     the time specified. Zero if a timeout or unrecoverable error
    213     ///     occurred.
    214     //------------------------------------------------------------------
    215     T
    216     WaitForSetValueBits (T bits, const TimeValue *abstime = NULL)
    217     {
    218         int err = 0;
    219         // pthread_cond_timedwait() or pthread_cond_wait() will atomically
    220         // unlock the mutex and wait for the condition to be set. When either
    221         // function returns, they will re-lock the mutex. We use an auto lock/unlock
    222         // class (Mutex::Locker) to allow us to return at any point in this
    223         // function and not have to worry about unlocking the mutex.
    224         Mutex::Locker locker(m_mutex);
    225 #ifdef DB_PTHREAD_LOG_EVENTS
    226         printf("%s (bits = 0x%8.8x, abstime = %p), m_value = 0x%8.8x\n", __FUNCTION__, bits, abstime, m_value);
    227 #endif
    228         while (err == 0 && ((m_value & bits) == 0))
    229         {
    230             err = m_condition.Wait (m_mutex, abstime);
    231         }
    232 #ifdef DB_PTHREAD_LOG_EVENTS
    233         printf("%s (bits = 0x%8.8x), m_value = 0x%8.8x, returning 0x%8.8x\n", __FUNCTION__, bits, m_value, m_value & bits);
    234 #endif
    235 
    236         return m_value & bits;
    237     }
    238 
    239     //------------------------------------------------------------------
    240     /// Wait for bits to be reset in \a m_value.
    241     ///
    242     /// Waits in a thread safe way for any bits in \a bits to get
    243     /// logically reset in \a m_value. If all bits are already reset in
    244     /// \a m_value, this function will return without waiting.
    245     ///
    246     /// It is possible for the value to be changed between the time
    247     /// the bits are reset and the time the waiting thread wakes up.
    248     /// If the bits are no set when the waiting thread wakes up, it will
    249     /// go back into a wait state.  It may be necessary for the calling
    250     /// code to use additional thread synchronization methods to detect
    251     /// transitory states.
    252     ///
    253     /// @param[in] bits
    254     ///     The bits we are waiting to be reset in \a m_value.
    255     ///
    256     /// @param[in] abstime
    257     ///     If non-NULL, the absolute time at which we should stop
    258     ///     waiting, else wait an infinite amount of time.
    259     ///
    260     /// @return
    261     ///     Zero on successful waits, or non-zero if a timeout or
    262     ///     unrecoverable error occurs.
    263     //------------------------------------------------------------------
    264     T
    265     WaitForResetValueBits (T bits, const TimeValue *abstime = NULL)
    266     {
    267         int err = 0;
    268 
    269         // pthread_cond_timedwait() or pthread_cond_wait() will atomically
    270         // unlock the mutex and wait for the condition to be set. When either
    271         // function returns, they will re-lock the mutex. We use an auto lock/unlock
    272         // class (Mutex::Locker) to allow us to return at any point in this
    273         // function and not have to worry about unlocking the mutex.
    274         Mutex::Locker locker(m_mutex);
    275 
    276 #ifdef DB_PTHREAD_LOG_EVENTS
    277         printf("%s (bits = 0x%8.8x, abstime = %p), m_value = 0x%8.8x\n", __FUNCTION__, bits, abstime, m_value);
    278 #endif
    279         while (err == 0 && ((m_value & bits) != 0))
    280         {
    281             err = m_condition.Wait (m_mutex, abstime);
    282         }
    283 
    284 #ifdef DB_PTHREAD_LOG_EVENTS
    285         printf("%s (bits = 0x%8.8x), m_value = 0x%8.8x, returning 0x%8.8x\n", __FUNCTION__, bits, m_value, m_value & bits);
    286 #endif
    287         return m_value & bits;
    288     }
    289 
    290     //------------------------------------------------------------------
    291     /// Wait for \a m_value to be equal to \a value.
    292     ///
    293     /// Waits in a thread safe way for \a m_value to be equal to \a
    294     /// value. If \a m_value is already equal to \a value, this
    295     /// function will return without waiting.
    296     ///
    297     /// It is possible for the value to be changed between the time
    298     /// the value is set and the time the waiting thread wakes up.
    299     /// If the value no longer matches the requested value when the
    300     /// waiting thread wakes up, it will go back into a wait state.  It
    301     /// may be necessary for the calling code to use additional thread
    302     /// synchronization methods to detect transitory states.
    303     ///
    304     /// @param[in] value
    305     ///     The value we want \a m_value to be equal to.
    306     ///
    307     /// @param[in] abstime
    308     ///     If non-NULL, the absolute time at which we should stop
    309     ///     waiting, else wait an infinite amount of time.
    310     ///
    311     /// @param[out] timed_out
    312     ///     If not null, set to true if we return because of a time out,
    313     ///     and false if the value was set.
    314     ///
    315     /// @return
    316     ///     @li \b true if the \a m_value is equal to \a value
    317     ///     @li \b false otherwise
    318     //------------------------------------------------------------------
    319     bool
    320     WaitForValueEqualTo (T value, const TimeValue *abstime = NULL, bool *timed_out = NULL)
    321     {
    322         int err = 0;
    323         // pthread_cond_timedwait() or pthread_cond_wait() will atomically
    324         // unlock the mutex and wait for the condition to be set. When either
    325         // function returns, they will re-lock the mutex. We use an auto lock/unlock
    326         // class (Mutex::Locker) to allow us to return at any point in this
    327         // function and not have to worry about unlocking the mutex.
    328         Mutex::Locker locker(m_mutex);
    329 
    330 #ifdef DB_PTHREAD_LOG_EVENTS
    331         printf("%s (value = 0x%8.8x, abstime = %p), m_value = 0x%8.8x\n", __FUNCTION__, value, abstime, m_value);
    332 #endif
    333         if (timed_out)
    334             *timed_out = false;
    335 
    336         while (err == 0 && m_value != value)
    337         {
    338             err = m_condition.Wait (m_mutex, abstime, timed_out);
    339         }
    340 
    341         return m_value == value;
    342     }
    343 
    344     //------------------------------------------------------------------
    345     /// Wait for \a m_value to be equal to \a value and then set it to
    346     /// a new value.
    347     ///
    348     /// Waits in a thread safe way for \a m_value to be equal to \a
    349     /// value and then sets \a m_value to \a new_value. If \a m_value
    350     /// is already equal to \a value, this function will immediately
    351     /// set \a m_value to \a new_value and return without waiting.
    352     ///
    353     /// It is possible for the value to be changed between the time
    354     /// the value is set and the time the waiting thread wakes up.
    355     /// If the value no longer matches the requested value when the
    356     /// waiting thread wakes up, it will go back into a wait state.  It
    357     /// may be necessary for the calling code to use additional thread
    358     /// synchronization methods to detect transitory states.
    359     ///
    360     /// @param[in] value
    361     ///     The value we want \a m_value to be equal to.
    362     ///
    363     /// @param[in] new_value
    364     ///     The value to which \a m_value will be set if \b true is
    365     ///     returned.
    366     ///
    367     /// @param[in] abstime
    368     ///     If non-NULL, the absolute time at which we should stop
    369     ///     waiting, else wait an infinite amount of time.
    370     ///
    371     /// @param[out] timed_out
    372     ///     If not null, set to true if we return because of a time out,
    373     ///     and false if the value was set.
    374     ///
    375     /// @return
    376     ///     @li \b true if the \a m_value became equal to \a value
    377     ///     @li \b false otherwise
    378     //------------------------------------------------------------------
    379     bool
    380     WaitForValueEqualToAndSetValueTo (T wait_value, T new_value, const TimeValue *abstime = NULL, bool *timed_out = NULL)
    381     {
    382         int err = 0;
    383         // pthread_cond_timedwait() or pthread_cond_wait() will atomically
    384         // unlock the mutex and wait for the condition to be set. When either
    385         // function returns, they will re-lock the mutex. We use an auto lock/unlock
    386         // class (Mutex::Locker) to allow us to return at any point in this
    387         // function and not have to worry about unlocking the mutex.
    388         Mutex::Locker locker(m_mutex);
    389 
    390 #ifdef DB_PTHREAD_LOG_EVENTS
    391         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);
    392 #endif
    393         if (timed_out)
    394             *timed_out = false;
    395 
    396         while (err == 0 && m_value != wait_value)
    397         {
    398             err = m_condition.Wait (m_mutex, abstime, timed_out);
    399         }
    400 
    401         if (m_value == wait_value)
    402         {
    403             m_value = new_value;
    404             return true;
    405         }
    406 
    407         return false;
    408     }
    409 
    410 
    411     //------------------------------------------------------------------
    412     /// Wait for \a m_value to not be equal to \a value.
    413     ///
    414     /// Waits in a thread safe way for \a m_value to not be equal to \a
    415     /// value. If \a m_value is already not equal to \a value, this
    416     /// function will return without waiting.
    417     ///
    418     /// It is possible for the value to be changed between the time
    419     /// the value is set and the time the waiting thread wakes up.
    420     /// If the value is equal to the test value when the waiting thread
    421     /// wakes up, it will go back into a wait state.  It may be
    422     /// necessary for the calling code to use additional thread
    423     /// synchronization methods to detect transitory states.
    424     ///
    425     /// @param[in] value
    426     ///     The value we want \a m_value to not be equal to.
    427     ///
    428     /// @param[out] new_value
    429     ///     The new value if \b true is returned.
    430     ///
    431     /// @param[in] abstime
    432     ///     If non-NULL, the absolute time at which we should stop
    433     ///     waiting, else wait an infinite amount of time.
    434     ///
    435     /// @return
    436     ///     @li \b true if the \a m_value is equal to \a value
    437     ///     @li \b false otherwise
    438     //------------------------------------------------------------------
    439     bool
    440     WaitForValueNotEqualTo (T value, T &new_value, const TimeValue *abstime = NULL)
    441     {
    442         int err = 0;
    443         // pthread_cond_timedwait() or pthread_cond_wait() will atomically
    444         // unlock the mutex and wait for the condition to be set. When either
    445         // function returns, they will re-lock the mutex. We use an auto lock/unlock
    446         // class (Mutex::Locker) to allow us to return at any point in this
    447         // function and not have to worry about unlocking the mutex.
    448         Mutex::Locker locker(m_mutex);
    449 #ifdef DB_PTHREAD_LOG_EVENTS
    450         printf("%s (value = 0x%8.8x, abstime = %p), m_value = 0x%8.8x\n", __FUNCTION__, value, abstime, m_value);
    451 #endif
    452         while (err == 0 && m_value == value)
    453         {
    454             err = m_condition.Wait (m_mutex, abstime);
    455         }
    456 
    457         if (m_value != value)
    458         {
    459             new_value = m_value;
    460             return true;
    461         }
    462         return false;
    463     }
    464 
    465 protected:
    466     //----------------------------------------------------------------------
    467     // pthread condition and mutex variable to controll access and allow
    468     // blocking between the main thread and the spotlight index thread.
    469     //----------------------------------------------------------------------
    470     T           m_value;        ///< The templatized value T that we are protecting access to
    471     mutable Mutex m_mutex;      ///< The mutex to use when accessing the data
    472     Condition   m_condition;    ///< The pthread condition variable to use for signaling that data available or changed.
    473 
    474 private:
    475 
    476     //------------------------------------------------------------------
    477     /// Broadcast if needed.
    478     ///
    479     /// Check to see if we need to broadcast to our condition variable
    480     /// depedning on the \a old_value and on the \a broadcast_type.
    481     ///
    482     /// If \a broadcast_type is eBroadcastNever, no broadcast will be
    483     /// sent.
    484     ///
    485     /// If \a broadcast_type is eBroadcastAlways, the condition variable
    486     /// will always be broadcast.
    487     ///
    488     /// If \a broadcast_type is eBroadcastOnChange, the condition
    489     /// variable be broadcast if the owned value changes.
    490     //------------------------------------------------------------------
    491     void
    492     Broadcast (T old_value, PredicateBroadcastType broadcast_type)
    493     {
    494         bool broadcast = (broadcast_type == eBroadcastAlways) || ((broadcast_type == eBroadcastOnChange) && old_value != m_value);
    495 #ifdef DB_PTHREAD_LOG_EVENTS
    496         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);
    497 #endif
    498         if (broadcast)
    499             m_condition.Broadcast();
    500     }
    501 
    502 
    503     DISALLOW_COPY_AND_ASSIGN(Predicate);
    504 };
    505 
    506 } // namespace lldb_private
    507 
    508 #endif  // #if defined(__cplusplus)
    509 #endif // #ifndef liblldb_Predicate_h_
    510