| //===-- Mutex.h -------------------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef liblldb_Mutex_h_ |
| #define liblldb_Mutex_h_ |
| #if defined(__cplusplus) |
| |
| #include "lldb/lldb-types.h" |
| #include <assert.h> |
| |
| #ifdef LLDB_CONFIGURATION_DEBUG |
| #include <string> |
| #endif |
| |
| namespace lldb_private { |
| |
| //---------------------------------------------------------------------- |
| /// @class Mutex Mutex.h "lldb/Host/Mutex.h" |
| /// @brief A C++ wrapper class for pthread mutexes. |
| //---------------------------------------------------------------------- |
| class Mutex |
| { |
| public: |
| friend class Locker; |
| friend class Condition; |
| |
| enum Type |
| { |
| eMutexTypeNormal, ///< Mutex that can't recursively entered by the same thread |
| eMutexTypeRecursive ///< Mutex can be recursively entered by the same thread |
| }; |
| |
| //------------------------------------------------------------------ |
| /// @class Mutex::Locker |
| /// |
| /// A scoped locking class that allows a variety of pthread mutex |
| /// objects to have a mutex locked when an Mutex::Locker |
| /// object is created, and unlocked when it goes out of scope or |
| /// when the Mutex::Locker::Reset(pthread_mutex_t *) |
| /// is called. This provides an exception safe way to lock a mutex |
| /// in a scope. |
| //------------------------------------------------------------------ |
| class Locker |
| { |
| public: |
| //-------------------------------------------------------------- |
| /// Default constructor. |
| /// |
| /// This will create a scoped mutex locking object that doesn't |
| /// have a mutex to lock. One will need to be provided using the |
| /// Mutex::Locker::Reset(pthread_mutex_t *) method. |
| /// |
| /// @see Mutex::Locker::Reset(pthread_mutex_t *) |
| //-------------------------------------------------------------- |
| Locker(); |
| |
| //-------------------------------------------------------------- |
| /// Constructor with a Mutex object. |
| /// |
| /// This will create a scoped mutex locking object that extracts |
| /// the mutex owned by \a m and locks it. |
| /// |
| /// @param[in] m |
| /// An instance of a Mutex object that contains a |
| /// valid mutex object. |
| //-------------------------------------------------------------- |
| Locker(Mutex& m); |
| |
| //-------------------------------------------------------------- |
| /// Constructor with a Mutex object pointer. |
| /// |
| /// This will create a scoped mutex locking object that extracts |
| /// the mutex owned by a m and locks it. |
| /// |
| /// @param[in] m |
| /// A pointer to instance of a Mutex object that |
| /// contains a valid mutex object. |
| //-------------------------------------------------------------- |
| Locker(Mutex* m); |
| |
| //-------------------------------------------------------------- |
| /// Desstructor |
| /// |
| /// Unlocks any valid pthread_mutex_t that this object may |
| /// contain. |
| //-------------------------------------------------------------- |
| ~Locker(); |
| |
| //-------------------------------------------------------------- |
| /// Change the contained mutex. |
| /// |
| /// Unlock the current mutex in this object (if it contains a |
| /// valid mutex) and lock the new \a mutex object if it is |
| /// non-NULL. |
| //-------------------------------------------------------------- |
| void |
| Lock (Mutex &mutex); |
| |
| void |
| Lock (Mutex *mutex) |
| { |
| if (mutex) |
| Lock(*mutex); |
| } |
| |
| //-------------------------------------------------------------- |
| /// Change the contained mutex only if the mutex can be locked. |
| /// |
| /// Unlock the current mutex in this object (if it contains a |
| /// valid mutex) and try to lock \a mutex. If \a mutex can be |
| /// locked this object will take ownership of the lock and will |
| /// unlock it when it goes out of scope or Reset or TryLock are |
| /// called again. If the mutex is already locked, this object |
| /// will not take ownership of the mutex. |
| /// |
| /// @return |
| /// Returns \b true if the lock was aquired and the this |
| /// object will unlock the mutex when it goes out of scope, |
| /// returns \b false otherwise. |
| //-------------------------------------------------------------- |
| bool |
| TryLock (Mutex &mutex, const char *failure_message = NULL); |
| |
| bool |
| TryLock (Mutex *mutex, const char *failure_message = NULL) |
| { |
| if (mutex) |
| return TryLock(*mutex, failure_message); |
| else |
| return false; |
| } |
| |
| void |
| Unlock (); |
| |
| protected: |
| //-------------------------------------------------------------- |
| /// Member variables |
| //-------------------------------------------------------------- |
| Mutex *m_mutex_ptr; |
| |
| private: |
| Locker(const Locker&); |
| const Locker& operator=(const Locker&); |
| }; |
| |
| |
| //------------------------------------------------------------------ |
| /// Default constructor. |
| /// |
| /// Creates a pthread mutex with no attributes. |
| //------------------------------------------------------------------ |
| Mutex(); |
| |
| //------------------------------------------------------------------ |
| /// Default constructor. |
| /// |
| /// Creates a pthread mutex with \a type as the mutex type. |
| /// Valid values for \a type include: |
| /// @li Mutex::Type::eMutexTypeNormal |
| /// @li Mutex::Type::eMutexTypeRecursive |
| /// |
| /// @param[in] type |
| /// The type of the mutex. |
| /// |
| /// @see ::pthread_mutexattr_settype() |
| //------------------------------------------------------------------ |
| Mutex(Mutex::Type type); |
| |
| //------------------------------------------------------------------ |
| /// Destructor. |
| /// |
| /// Destroys the mutex owned by this object. |
| //------------------------------------------------------------------ |
| #ifdef LLDB_CONFIGURATION_DEBUG |
| virtual |
| #endif |
| ~Mutex(); |
| |
| //------------------------------------------------------------------ |
| /// Lock the mutex. |
| /// |
| /// Locks the mutex owned by this object. If the mutex is already |
| /// locked, the calling thread will block until the mutex becomes |
| /// available. |
| /// |
| /// @return |
| /// The error code from \c pthread_mutex_lock(). |
| //------------------------------------------------------------------ |
| #ifdef LLDB_CONFIGURATION_DEBUG |
| virtual |
| #endif |
| int |
| Lock(); |
| |
| //------------------------------------------------------------------ |
| /// Try to lock the mutex. |
| /// |
| /// Attempts to lock the mutex owned by this object without blocking. |
| /// If the mutex is already locked, TryLock() will not block waiting |
| /// for the mutex, but will return an error condition. |
| /// |
| /// @return |
| /// The error code from \c pthread_mutex_trylock(). |
| //------------------------------------------------------------------ |
| #ifdef LLDB_CONFIGURATION_DEBUG |
| virtual |
| #endif |
| int |
| TryLock(const char *failure_message = NULL); |
| |
| //------------------------------------------------------------------ |
| /// Unlock the mutex. |
| /// |
| /// If the current thread holds the lock on the owned mutex, then |
| /// Unlock() will unlock the mutex. Calling Unlock() on this object |
| /// when the calling thread does not hold the lock will result in |
| /// undefined behavior. |
| /// |
| /// @return |
| /// The error code from \c pthread_mutex_unlock(). |
| //------------------------------------------------------------------ |
| #ifdef LLDB_CONFIGURATION_DEBUG |
| virtual |
| #endif |
| int |
| Unlock(); |
| |
| protected: |
| //------------------------------------------------------------------ |
| // Member variables |
| //------------------------------------------------------------------ |
| // TODO: Hide the mutex in the implementation file in case we ever need to port to an |
| // architecture that doesn't have pthread mutexes. |
| lldb::mutex_t m_mutex; ///< The OS mutex object. |
| |
| private: |
| //------------------------------------------------------------------ |
| /// Mutex get accessor. |
| /// |
| /// @return |
| /// A pointer to the pthread mutex object owned by this object. |
| //------------------------------------------------------------------ |
| lldb::mutex_t * |
| GetMutex(); |
| |
| Mutex(const Mutex&); |
| const Mutex& operator=(const Mutex&); |
| }; |
| |
| #ifdef LLDB_CONFIGURATION_DEBUG |
| class TrackingMutex : public Mutex |
| { |
| public: |
| TrackingMutex() : Mutex() {} |
| TrackingMutex(Mutex::Type type) : Mutex (type) {} |
| |
| virtual |
| ~TrackingMutex() {} |
| |
| virtual int |
| Unlock (); |
| |
| virtual int |
| TryLock (const char *failure_message = NULL) |
| { |
| int return_value = Mutex::TryLock(); |
| if (return_value != 0 && failure_message != NULL) |
| { |
| m_failure_message.assign(failure_message); |
| m_thread_that_tried = pthread_self(); |
| } |
| return return_value; |
| } |
| |
| protected: |
| pthread_t m_thread_that_tried; |
| std::string m_failure_message; |
| }; |
| |
| class LoggingMutex : public Mutex |
| { |
| public: |
| LoggingMutex() : Mutex(),m_locked(false) {} |
| LoggingMutex(Mutex::Type type) : Mutex (type),m_locked(false) {} |
| |
| virtual |
| ~LoggingMutex() {} |
| |
| virtual int |
| Lock (); |
| |
| virtual int |
| Unlock (); |
| |
| virtual int |
| TryLock (const char *failure_message = NULL); |
| protected: |
| bool m_locked; |
| }; |
| #endif |
| |
| } // namespace lldb_private |
| |
| #endif // #if defined(__cplusplus) |
| #endif |