DISTRHO Plugin Framework
Mutex.hpp
1 /*
2  * DISTRHO Plugin Framework (DPF)
3  * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any purpose with
6  * or without fee is hereby granted, provided that the above copyright notice and this
7  * permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
10  * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
11  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
13  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #ifndef DISTRHO_MUTEX_HPP_INCLUDED
18 #define DISTRHO_MUTEX_HPP_INCLUDED
19 
20 #include "../DistrhoUtils.hpp"
21 
22 #ifdef DISTRHO_OS_WINDOWS
23 # include <winsock2.h>
24 # include <windows.h>
25 #endif
26 
27 #include <pthread.h>
28 
29 START_NAMESPACE_DISTRHO
30 
31 // -----------------------------------------------------------------------
32 // Mutex class
33 
34 class Mutex
35 {
36 public:
37  /*
38  * Constructor.
39  */
40  Mutex() noexcept
41  : fMutex()
42  {
43  pthread_mutex_init(&fMutex, nullptr);
44  }
45 
46  /*
47  * Destructor.
48  */
49  ~Mutex() noexcept
50  {
51  pthread_mutex_destroy(&fMutex);
52  }
53 
54  /*
55  * Lock the mutex.
56  */
57  void lock() const noexcept
58  {
59  pthread_mutex_lock(&fMutex);
60  }
61 
62  /*
63  * Try to lock the mutex.
64  * Returns true if successful.
65  */
66  bool tryLock() const noexcept
67  {
68  return (pthread_mutex_trylock(&fMutex) == 0);
69  }
70 
71  /*
72  * Unlock the mutex.
73  */
74  void unlock() const noexcept
75  {
76  pthread_mutex_unlock(&fMutex);
77  }
78 
79 private:
80  mutable pthread_mutex_t fMutex;
81 
82  DISTRHO_PREVENT_HEAP_ALLOCATION
83  DISTRHO_DECLARE_NON_COPY_CLASS(Mutex)
84 };
85 
86 // -----------------------------------------------------------------------
87 // RecursiveMutex class
88 
90 {
91 public:
92  /*
93  * Constructor.
94  */
95  RecursiveMutex() noexcept
96 #ifdef DISTRHO_OS_WINDOWS
97  : fSection()
98 #else
99  : fMutex()
100 #endif
101  {
102 #ifdef DISTRHO_OS_WINDOWS
103  InitializeCriticalSection(&fSection);
104 #else
105  pthread_mutexattr_t atts;
106  pthread_mutexattr_init(&atts);
107  pthread_mutexattr_settype(&atts, PTHREAD_MUTEX_RECURSIVE);
108  pthread_mutex_init(&fMutex, &atts);
109  pthread_mutexattr_destroy(&atts);
110 #endif
111  }
112 
113  /*
114  * Destructor.
115  */
116  ~RecursiveMutex() noexcept
117  {
118 #ifdef DISTRHO_OS_WINDOWS
119  DeleteCriticalSection(&fSection);
120 #else
121  pthread_mutex_destroy(&fMutex);
122 #endif
123  }
124 
125  /*
126  * Lock the mutex.
127  */
128  void lock() const noexcept
129  {
130 #ifdef DISTRHO_OS_WINDOWS
131  EnterCriticalSection(&fSection);
132 #else
133  pthread_mutex_lock(&fMutex);
134 #endif
135  }
136 
137  /*
138  * Try to lock the mutex.
139  * Returns true if successful.
140  */
141  bool tryLock() const noexcept
142  {
143 #ifdef DISTRHO_OS_WINDOWS
144  return (TryEnterCriticalSection(&fSection) != FALSE);
145 #else
146  return (pthread_mutex_trylock(&fMutex) == 0);
147 #endif
148  }
149 
150  /*
151  * Unlock the mutex.
152  */
153  void unlock() const noexcept
154  {
155 #ifdef DISTRHO_OS_WINDOWS
156  LeaveCriticalSection(&fSection);
157 #else
158  pthread_mutex_unlock(&fMutex);
159 #endif
160  }
161 
162 private:
163 #ifdef DISTRHO_OS_WINDOWS
164  mutable CRITICAL_SECTION fSection;
165 #else
166  mutable pthread_mutex_t fMutex;
167 #endif
168 
169  DISTRHO_PREVENT_HEAP_ALLOCATION
170  DISTRHO_DECLARE_NON_COPY_CLASS(RecursiveMutex)
171 };
172 
173 // -----------------------------------------------------------------------
174 // Helper class to lock&unlock a mutex during a function scope.
175 
176 template <class Mutex>
178 {
179 public:
180  ScopeLocker(const Mutex& mutex) noexcept
181  : fMutex(mutex)
182  {
183  fMutex.lock();
184  }
185 
186  ~ScopeLocker() noexcept
187  {
188  fMutex.unlock();
189  }
190 
191 private:
192  const Mutex& fMutex;
193 
194  DISTRHO_PREVENT_HEAP_ALLOCATION
195  DISTRHO_DECLARE_NON_COPY_CLASS(ScopeLocker)
196 };
197 
198 // -----------------------------------------------------------------------
199 // Helper class to try-lock&unlock a mutex during a function scope.
200 
201 template <class Mutex>
203 {
204 public:
205  ScopeTryLocker(const Mutex& mutex) noexcept
206  : fMutex(mutex),
207  fLocked(mutex.tryLock()) {}
208 
209  ~ScopeTryLocker() noexcept
210  {
211  if (fLocked)
212  fMutex.unlock();
213  }
214 
215  bool wasLocked() const noexcept
216  {
217  return fLocked;
218  }
219 
220  bool wasNotLocked() const noexcept
221  {
222  return !fLocked;
223  }
224 
225 private:
226  const Mutex& fMutex;
227  const bool fLocked;
228 
229  DISTRHO_PREVENT_HEAP_ALLOCATION
230  DISTRHO_DECLARE_NON_COPY_CLASS(ScopeTryLocker)
231 };
232 
233 // -----------------------------------------------------------------------
234 // Helper class to unlock&lock a mutex during a function scope.
235 
236 template <class Mutex>
238 {
239 public:
240  ScopeUnlocker(const Mutex& mutex) noexcept
241  : fMutex(mutex)
242  {
243  fMutex.unlock();
244  }
245 
246  ~ScopeUnlocker() noexcept
247  {
248  fMutex.lock();
249  }
250 
251 private:
252  const Mutex& fMutex;
253 
254  DISTRHO_PREVENT_HEAP_ALLOCATION
255  DISTRHO_DECLARE_NON_COPY_CLASS(ScopeUnlocker)
256 };
257 
258 // -----------------------------------------------------------------------
259 // Define types
260 
263 
266 
269 
270 // -----------------------------------------------------------------------
271 
272 END_NAMESPACE_DISTRHO
273 
274 #endif // DISTRHO_MUTEX_HPP_INCLUDED
Definition: Mutex.hpp:89
Definition: Mutex.hpp:177
Definition: Mutex.hpp:202
Definition: Mutex.hpp:34
Definition: Mutex.hpp:237