Home | History | Annotate | Download | only in Host
      1 //===-- Mutex.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_Mutex_h_
     11 #define liblldb_Mutex_h_
     12 #if defined(__cplusplus)
     13 
     14 #include <pthread.h>
     15 #include <assert.h>
     16 
     17 #ifdef LLDB_CONFIGURATION_DEBUG
     18 #include <string>
     19 #endif
     20 
     21 namespace lldb_private {
     22 
     23 //----------------------------------------------------------------------
     24 /// @class Mutex Mutex.h "lldb/Host/Mutex.h"
     25 /// @brief A C++ wrapper class for pthread mutexes.
     26 //----------------------------------------------------------------------
     27 class Mutex
     28 {
     29 public:
     30     friend class Locker;
     31     friend class Condition;
     32 
     33     enum Type
     34     {
     35         eMutexTypeNormal,       ///< Mutex that can't recursively entered by the same thread
     36         eMutexTypeRecursive     ///< Mutex can be recursively entered by the same thread
     37     };
     38 
     39     //------------------------------------------------------------------
     40     /// @class Mutex::Locker
     41     ///
     42     /// A scoped locking class that allows a variety of pthread mutex
     43     /// objects to have a mutex locked when an Mutex::Locker
     44     /// object is created, and unlocked when it goes out of scope or
     45     /// when the Mutex::Locker::Reset(pthread_mutex_t *)
     46     /// is called. This provides an exception safe way to lock a mutex
     47     /// in a scope.
     48     //------------------------------------------------------------------
     49     class Locker
     50     {
     51     public:
     52         //--------------------------------------------------------------
     53         /// Default constructor.
     54         ///
     55         /// This will create a scoped mutex locking object that doesn't
     56         /// have a mutex to lock. One will need to be provided using the
     57         /// Mutex::Locker::Reset(pthread_mutex_t *) method.
     58         ///
     59         /// @see Mutex::Locker::Reset(pthread_mutex_t *)
     60         //--------------------------------------------------------------
     61         Locker();
     62 
     63         //--------------------------------------------------------------
     64         /// Constructor with a Mutex object.
     65         ///
     66         /// This will create a scoped mutex locking object that extracts
     67         /// the mutex owned by \a m and locks it.
     68         ///
     69         /// @param[in] m
     70         ///     An instance of a Mutex object that contains a
     71         ///     valid mutex object.
     72         //--------------------------------------------------------------
     73         Locker(Mutex& m);
     74 
     75         //--------------------------------------------------------------
     76         /// Constructor with a Mutex object pointer.
     77         ///
     78         /// This will create a scoped mutex locking object that extracts
     79         /// the mutex owned by a m and locks it.
     80         ///
     81         /// @param[in] m
     82         ///     A pointer to instance of a Mutex object that
     83         ///     contains a valid mutex object.
     84         //--------------------------------------------------------------
     85         Locker(Mutex* m);
     86 
     87         //--------------------------------------------------------------
     88         /// Desstructor
     89         ///
     90         /// Unlocks any valid pthread_mutex_t that this object may
     91         /// contain.
     92         //--------------------------------------------------------------
     93         ~Locker();
     94 
     95         //--------------------------------------------------------------
     96         /// Change the contained mutex.
     97         ///
     98         /// Unlock the current mutex in this object (if it contains a
     99         /// valid mutex) and lock the new \a mutex object if it is
    100         /// non-NULL.
    101         //--------------------------------------------------------------
    102         void
    103         Lock (Mutex &mutex);
    104 
    105         void
    106         Lock (Mutex *mutex)
    107         {
    108             if (mutex)
    109                 Lock(*mutex);
    110         }
    111 
    112         //--------------------------------------------------------------
    113         /// Change the contained mutex only if the mutex can be locked.
    114         ///
    115         /// Unlock the current mutex in this object (if it contains a
    116         /// valid mutex) and try to lock \a mutex. If \a mutex can be
    117         /// locked this object will take ownership of the lock and will
    118         /// unlock it when it goes out of scope or Reset or TryLock are
    119         /// called again. If the mutex is already locked, this object
    120         /// will not take ownership of the mutex.
    121         ///
    122         /// @return
    123         ///     Returns \b true if the lock was aquired and the this
    124         ///     object will unlock the mutex when it goes out of scope,
    125         ///     returns \b false otherwise.
    126         //--------------------------------------------------------------
    127         bool
    128         TryLock (Mutex &mutex, const char *failure_message = NULL);
    129 
    130         bool
    131         TryLock (Mutex *mutex, const char *failure_message = NULL)
    132         {
    133             if (mutex)
    134                 return TryLock(*mutex, failure_message);
    135             else
    136                 return false;
    137         }
    138 
    139         void
    140         Unlock ();
    141 
    142     protected:
    143         //--------------------------------------------------------------
    144         /// Member variables
    145         //--------------------------------------------------------------
    146         Mutex *m_mutex_ptr;
    147 
    148     private:
    149         Locker(const Locker&);
    150         const Locker& operator=(const Locker&);
    151     };
    152 
    153 
    154     //------------------------------------------------------------------
    155     /// Default constructor.
    156     ///
    157     /// Creates a pthread mutex with no attributes.
    158     //------------------------------------------------------------------
    159     Mutex();
    160 
    161     //------------------------------------------------------------------
    162     /// Default constructor.
    163     ///
    164     /// Creates a pthread mutex with \a type as the mutex type.
    165     /// Valid values for \a type include:
    166     ///     @li Mutex::Type::eMutexTypeNormal
    167     ///     @li Mutex::Type::eMutexTypeRecursive
    168     ///
    169     /// @param[in] type
    170     ///     The type of the mutex.
    171     ///
    172     /// @see ::pthread_mutexattr_settype()
    173     //------------------------------------------------------------------
    174     Mutex(Mutex::Type type);
    175 
    176     //------------------------------------------------------------------
    177     /// Destructor.
    178     ///
    179     /// Destroys the mutex owned by this object.
    180     //------------------------------------------------------------------
    181 #ifdef LLDB_CONFIGURATION_DEBUG
    182     virtual
    183 #endif
    184     ~Mutex();
    185 
    186     //------------------------------------------------------------------
    187     /// Lock the mutex.
    188     ///
    189     /// Locks the mutex owned by this object. If the mutex is already
    190     /// locked, the calling thread will block until the mutex becomes
    191     /// available.
    192     ///
    193     /// @return
    194     ///     The error code from \c pthread_mutex_lock().
    195     //------------------------------------------------------------------
    196 #ifdef LLDB_CONFIGURATION_DEBUG
    197     virtual
    198 #endif
    199     int
    200     Lock();
    201 
    202     //------------------------------------------------------------------
    203     /// Try to lock the mutex.
    204     ///
    205     /// Attempts to lock the mutex owned by this object without blocking.
    206     /// If the mutex is already locked, TryLock() will not block waiting
    207     /// for the mutex, but will return an error condition.
    208     ///
    209     /// @return
    210     ///     The error code from \c pthread_mutex_trylock().
    211     //------------------------------------------------------------------
    212 #ifdef LLDB_CONFIGURATION_DEBUG
    213     virtual
    214 #endif
    215     int
    216     TryLock(const char *failure_message = NULL);
    217 
    218     //------------------------------------------------------------------
    219     /// Unlock the mutex.
    220     ///
    221     /// If the current thread holds the lock on the owned mutex, then
    222     /// Unlock() will unlock the mutex. Calling Unlock() on this object
    223     /// when the calling thread does not hold the lock will result in
    224     /// undefined behavior.
    225     ///
    226     /// @return
    227     ///     The error code from \c pthread_mutex_unlock().
    228     //------------------------------------------------------------------
    229 #ifdef LLDB_CONFIGURATION_DEBUG
    230     virtual
    231 #endif
    232     int
    233     Unlock();
    234 
    235 protected:
    236     //------------------------------------------------------------------
    237     // Member variables
    238     //------------------------------------------------------------------
    239     // TODO: Hide the mutex in the implementation file in case we ever need to port to an
    240     // architecture that doesn't have pthread mutexes.
    241     pthread_mutex_t m_mutex; ///< The pthread mutex object.
    242 
    243 private:
    244     //------------------------------------------------------------------
    245     /// Mutex get accessor.
    246     ///
    247     /// @return
    248     ///     A pointer to the pthread mutex object owned by this object.
    249     //------------------------------------------------------------------
    250     pthread_mutex_t *
    251     GetMutex();
    252 
    253     Mutex(const Mutex&);
    254     const Mutex& operator=(const Mutex&);
    255 };
    256 
    257 #ifdef LLDB_CONFIGURATION_DEBUG
    258 class TrackingMutex : public Mutex
    259 {
    260 public:
    261     TrackingMutex() : Mutex()  {}
    262     TrackingMutex(Mutex::Type type) : Mutex (type) {}
    263 
    264     virtual
    265     ~TrackingMutex() {}
    266 
    267     virtual int
    268     Unlock ();
    269 
    270     virtual int
    271     TryLock (const char *failure_message = NULL)
    272     {
    273         int return_value = Mutex::TryLock();
    274         if (return_value != 0 && failure_message != NULL)
    275         {
    276             m_failure_message.assign(failure_message);
    277             m_thread_that_tried = pthread_self();
    278         }
    279         return return_value;
    280     }
    281 
    282 protected:
    283     pthread_t m_thread_that_tried;
    284     std::string m_failure_message;
    285 };
    286 
    287 class LoggingMutex : public Mutex
    288 {
    289 public:
    290     LoggingMutex() : Mutex(),m_locked(false)  {}
    291     LoggingMutex(Mutex::Type type) : Mutex (type),m_locked(false) {}
    292 
    293     virtual
    294     ~LoggingMutex() {}
    295 
    296     virtual int
    297     Lock ();
    298 
    299     virtual int
    300     Unlock ();
    301 
    302     virtual int
    303     TryLock (const char *failure_message = NULL);
    304 protected:
    305     bool m_locked;
    306 };
    307 #endif
    308 
    309 } // namespace lldb_private
    310 
    311 #endif  // #if defined(__cplusplus)
    312 #endif
    313