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