1 //===-- ProcessRunLock.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_ProcessRunLock_h_
11 #define liblldb_ProcessRunLock_h_
12 #if defined(__cplusplus)
13 
14 #include "lldb/Host/Mutex.h"
15 #include "lldb/Host/Condition.h"
16 #include <pthread.h>
17 #include <stdint.h>
18 #include <time.h>
19 
20 //----------------------------------------------------------------------
21 /// Enumerations for broadcasting.
22 //----------------------------------------------------------------------
23 namespace lldb_private {
24 
25 //----------------------------------------------------------------------
26 /// @class ProcessRunLock ProcessRunLock.h "lldb/Host/ProcessRunLock.h"
27 /// @brief A class used to prevent the process from starting while other
28 /// threads are accessing its data, and prevent access to its data while
29 /// it is running.
30 //----------------------------------------------------------------------
31 
32 class ProcessRunLock
33 {
34 public:
ProcessRunLock()35     ProcessRunLock () :
36         m_rwlock(),
37         m_running(false)
38     {
39         int err = ::pthread_rwlock_init(&m_rwlock, NULL); (void)err;
40 //#if LLDB_CONFIGURATION_DEBUG
41 //        assert(err == 0);
42 //#endif
43     }
44 
~ProcessRunLock()45     ~ProcessRunLock ()
46     {
47         int err = ::pthread_rwlock_destroy (&m_rwlock); (void)err;
48 //#if LLDB_CONFIGURATION_DEBUG
49 //        assert(err == 0);
50 //#endif
51     }
52 
53     bool
ReadTryLock()54     ReadTryLock ()
55     {
56         ::pthread_rwlock_rdlock (&m_rwlock);
57         if (m_running == false)
58         {
59             return true;
60         }
61         ::pthread_rwlock_unlock (&m_rwlock);
62         return false;
63     }
64 
65     bool
ReadUnlock()66     ReadUnlock ()
67     {
68         return ::pthread_rwlock_unlock (&m_rwlock) == 0;
69     }
70 
71     bool
SetRunning()72     SetRunning()
73     {
74         ::pthread_rwlock_wrlock (&m_rwlock);
75         m_running = true;
76         ::pthread_rwlock_unlock (&m_rwlock);
77         return true;
78     }
79 
80     bool
TrySetRunning()81     TrySetRunning()
82     {
83         bool r;
84 
85         if (::pthread_rwlock_trywrlock (&m_rwlock) == 0)
86         {
87             r = !m_running;
88             m_running = true;
89             ::pthread_rwlock_unlock (&m_rwlock);
90             return r;
91         }
92         return false;
93     }
94 
95     bool
SetStopped()96     SetStopped ()
97     {
98         ::pthread_rwlock_wrlock (&m_rwlock);
99         m_running = false;
100         ::pthread_rwlock_unlock (&m_rwlock);
101         return true;
102     }
103 
104     class ProcessRunLocker
105     {
106     public:
ProcessRunLocker()107         ProcessRunLocker () :
108             m_lock (NULL)
109         {
110         }
111 
~ProcessRunLocker()112         ~ProcessRunLocker()
113         {
114             Unlock();
115         }
116 
117         // Try to lock the read lock, but only do so if there are no writers.
118         bool
TryLock(ProcessRunLock * lock)119         TryLock (ProcessRunLock *lock)
120         {
121             if (m_lock)
122             {
123                 if (m_lock == lock)
124                     return true; // We already have this lock locked
125                 else
126                     Unlock();
127             }
128             if (lock)
129             {
130                 if (lock->ReadTryLock())
131                 {
132                     m_lock = lock;
133                     return true;
134                 }
135             }
136             return false;
137         }
138 
139     protected:
140         void
Unlock()141         Unlock ()
142         {
143             if (m_lock)
144             {
145                 m_lock->ReadUnlock();
146                 m_lock = NULL;
147             }
148         }
149 
150         ProcessRunLock *m_lock;
151     private:
152         DISALLOW_COPY_AND_ASSIGN(ProcessRunLocker);
153     };
154 
155 protected:
156     pthread_rwlock_t m_rwlock;
157     bool m_running;
158 private:
159     DISALLOW_COPY_AND_ASSIGN(ProcessRunLock);
160 };
161 
162 } // namespace lldb_private
163 
164 #endif  // #if defined(__cplusplus)
165 #endif // #ifndef liblldb_ProcessRunLock_h_
166