• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
Lock(Mutex * mutex)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:
TrackingMutex()261     TrackingMutex() : Mutex()  {}
TrackingMutex(Mutex::Type type)262     TrackingMutex(Mutex::Type type) : Mutex (type) {}
263 
264     virtual
~TrackingMutex()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:
LoggingMutex()290     LoggingMutex() : Mutex(),m_locked(false)  {}
LoggingMutex(Mutex::Type type)291     LoggingMutex(Mutex::Type type) : Mutex (type),m_locked(false) {}
292 
293     virtual
~LoggingMutex()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