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
21namespace lldb_private {
22
23//----------------------------------------------------------------------
24/// @class Mutex Mutex.h "lldb/Host/Mutex.h"
25/// @brief A C++ wrapper class for pthread mutexes.
26//----------------------------------------------------------------------
27class Mutex
28{
29public:
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
235protected:
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
243private:
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
258class TrackingMutex : public Mutex
259{
260public:
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
282protected:
283    pthread_t m_thread_that_tried;
284    std::string m_failure_message;
285};
286
287class LoggingMutex : public Mutex
288{
289public:
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);
304protected:
305    bool m_locked;
306};
307#endif
308
309} // namespace lldb_private
310
311#endif  // #if defined(__cplusplus)
312#endif
313