diff options
Diffstat (limited to 'include/lldb/Host/Mutex.h')
-rw-r--r-- | include/lldb/Host/Mutex.h | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/include/lldb/Host/Mutex.h b/include/lldb/Host/Mutex.h new file mode 100644 index 000000000000..63f759efe366 --- /dev/null +++ b/include/lldb/Host/Mutex.h @@ -0,0 +1,312 @@ +//===-- 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 <pthread.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. + pthread_mutex_t m_mutex; ///< The pthread mutex object. + +private: + //------------------------------------------------------------------ + /// Mutex get accessor. + /// + /// @return + /// A pointer to the pthread mutex object owned by this object. + //------------------------------------------------------------------ + pthread_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 |