Mercurial > hg > pub > prymula > com
comparison DPF-Prymula-audioplugins/dpf/distrho/extra/Mutex.hpp @ 3:84e66ea83026
DPF-Prymula-audioplugins-0.231015-2
author | prymula <prymula76@outlook.com> |
---|---|
date | Mon, 16 Oct 2023 21:53:34 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2:cf2cb71d31dd | 3:84e66ea83026 |
---|---|
1 /* | |
2 * DISTRHO Plugin Framework (DPF) | |
3 * Copyright (C) 2012-2022 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 # ifndef NOMINMAX | |
24 # define NOMINMAX | |
25 # endif | |
26 # include <winsock2.h> | |
27 # include <windows.h> | |
28 #endif | |
29 | |
30 // FIXME make Mutex stop relying on pthread | |
31 #ifdef _MSC_VER | |
32 #define DISTRHO_OS_WINDOWS__TODO | |
33 #pragma NOTE(DPF Mutex implementation is TODO on MSVC) | |
34 #else | |
35 #include <pthread.h> | |
36 #endif | |
37 | |
38 START_NAMESPACE_DISTRHO | |
39 | |
40 class Signal; | |
41 | |
42 // ----------------------------------------------------------------------- | |
43 // Mutex class | |
44 | |
45 class Mutex | |
46 { | |
47 public: | |
48 /* | |
49 * Constructor. | |
50 */ | |
51 Mutex(const bool inheritPriority = true) noexcept | |
52 #ifdef DISTRHO_OS_WINDOWS__TODO | |
53 #else | |
54 : fMutex() | |
55 #endif | |
56 { | |
57 #ifdef DISTRHO_OS_WINDOWS__TODO | |
58 #else | |
59 pthread_mutexattr_t attr; | |
60 pthread_mutexattr_init(&attr); | |
61 pthread_mutexattr_setprotocol(&attr, inheritPriority ? PTHREAD_PRIO_INHERIT : PTHREAD_PRIO_NONE); | |
62 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); | |
63 pthread_mutex_init(&fMutex, &attr); | |
64 pthread_mutexattr_destroy(&attr); | |
65 #endif | |
66 } | |
67 | |
68 /* | |
69 * Destructor. | |
70 */ | |
71 ~Mutex() noexcept | |
72 { | |
73 #ifdef DISTRHO_OS_WINDOWS__TODO | |
74 #else | |
75 pthread_mutex_destroy(&fMutex); | |
76 #endif | |
77 } | |
78 | |
79 /* | |
80 * Lock the mutex. | |
81 */ | |
82 bool lock() const noexcept | |
83 { | |
84 #ifdef DISTRHO_OS_WINDOWS__TODO | |
85 #else | |
86 return (pthread_mutex_lock(&fMutex) == 0); | |
87 #endif | |
88 } | |
89 | |
90 /* | |
91 * Try to lock the mutex. | |
92 * Returns true if successful. | |
93 */ | |
94 bool tryLock() const noexcept | |
95 { | |
96 #ifdef DISTRHO_OS_WINDOWS__TODO | |
97 #else | |
98 return (pthread_mutex_trylock(&fMutex) == 0); | |
99 #endif | |
100 } | |
101 | |
102 /* | |
103 * Unlock the mutex. | |
104 */ | |
105 void unlock() const noexcept | |
106 { | |
107 #ifdef DISTRHO_OS_WINDOWS__TODO | |
108 #else | |
109 pthread_mutex_unlock(&fMutex); | |
110 #endif | |
111 } | |
112 | |
113 private: | |
114 #ifdef DISTRHO_OS_WINDOWS__TODO | |
115 #else | |
116 mutable pthread_mutex_t fMutex; | |
117 #endif | |
118 | |
119 DISTRHO_DECLARE_NON_COPYABLE(Mutex) | |
120 }; | |
121 | |
122 // ----------------------------------------------------------------------- | |
123 // RecursiveMutex class | |
124 | |
125 class RecursiveMutex | |
126 { | |
127 public: | |
128 /* | |
129 * Constructor. | |
130 */ | |
131 RecursiveMutex() noexcept | |
132 #ifdef DISTRHO_OS_WINDOWS | |
133 : fSection() | |
134 #else | |
135 : fMutex() | |
136 #endif | |
137 { | |
138 #ifdef DISTRHO_OS_WINDOWS | |
139 InitializeCriticalSection(&fSection); | |
140 #else | |
141 pthread_mutexattr_t attr; | |
142 pthread_mutexattr_init(&attr); | |
143 pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT); | |
144 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); | |
145 pthread_mutex_init(&fMutex, &attr); | |
146 pthread_mutexattr_destroy(&attr); | |
147 #endif | |
148 } | |
149 | |
150 /* | |
151 * Destructor. | |
152 */ | |
153 ~RecursiveMutex() noexcept | |
154 { | |
155 #ifdef DISTRHO_OS_WINDOWS | |
156 DeleteCriticalSection(&fSection); | |
157 #else | |
158 pthread_mutex_destroy(&fMutex); | |
159 #endif | |
160 } | |
161 | |
162 /* | |
163 * Lock the mutex. | |
164 */ | |
165 bool lock() const noexcept | |
166 { | |
167 #ifdef DISTRHO_OS_WINDOWS | |
168 EnterCriticalSection(&fSection); | |
169 return true; | |
170 #else | |
171 return (pthread_mutex_lock(&fMutex) == 0); | |
172 #endif | |
173 } | |
174 | |
175 /* | |
176 * Try to lock the mutex. | |
177 * Returns true if successful. | |
178 */ | |
179 bool tryLock() const noexcept | |
180 { | |
181 #ifdef DISTRHO_OS_WINDOWS | |
182 return (TryEnterCriticalSection(&fSection) != FALSE); | |
183 #else | |
184 return (pthread_mutex_trylock(&fMutex) == 0); | |
185 #endif | |
186 } | |
187 | |
188 /* | |
189 * Unlock the mutex. | |
190 */ | |
191 void unlock() const noexcept | |
192 { | |
193 #ifdef DISTRHO_OS_WINDOWS | |
194 LeaveCriticalSection(&fSection); | |
195 #else | |
196 pthread_mutex_unlock(&fMutex); | |
197 #endif | |
198 } | |
199 | |
200 private: | |
201 #ifdef DISTRHO_OS_WINDOWS | |
202 mutable CRITICAL_SECTION fSection; | |
203 #else | |
204 mutable pthread_mutex_t fMutex; | |
205 #endif | |
206 | |
207 DISTRHO_DECLARE_NON_COPYABLE(RecursiveMutex) | |
208 }; | |
209 | |
210 #ifndef _MSC_VER | |
211 // ----------------------------------------------------------------------- | |
212 // Signal class | |
213 | |
214 class Signal | |
215 { | |
216 public: | |
217 /* | |
218 * Constructor. | |
219 */ | |
220 Signal() noexcept | |
221 : fCondition(), | |
222 fMutex(), | |
223 fTriggered(false) | |
224 { | |
225 pthread_condattr_t cattr; | |
226 pthread_condattr_init(&cattr); | |
227 pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_PRIVATE); | |
228 pthread_cond_init(&fCondition, &cattr); | |
229 pthread_condattr_destroy(&cattr); | |
230 | |
231 pthread_mutexattr_t mattr; | |
232 pthread_mutexattr_init(&mattr); | |
233 pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT); | |
234 pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_NORMAL); | |
235 pthread_mutex_init(&fMutex, &mattr); | |
236 pthread_mutexattr_destroy(&mattr); | |
237 } | |
238 | |
239 /* | |
240 * Destructor. | |
241 */ | |
242 ~Signal() noexcept | |
243 { | |
244 pthread_cond_destroy(&fCondition); | |
245 pthread_mutex_destroy(&fMutex); | |
246 } | |
247 | |
248 /* | |
249 * Wait for a signal. | |
250 */ | |
251 void wait() noexcept | |
252 { | |
253 pthread_mutex_lock(&fMutex); | |
254 | |
255 while (! fTriggered) | |
256 { | |
257 try { | |
258 pthread_cond_wait(&fCondition, &fMutex); | |
259 } DISTRHO_SAFE_EXCEPTION("pthread_cond_wait"); | |
260 } | |
261 | |
262 fTriggered = false; | |
263 | |
264 pthread_mutex_unlock(&fMutex); | |
265 } | |
266 | |
267 /* | |
268 * Wake up all waiting threads. | |
269 */ | |
270 void signal() noexcept | |
271 { | |
272 pthread_mutex_lock(&fMutex); | |
273 | |
274 if (! fTriggered) | |
275 { | |
276 fTriggered = true; | |
277 pthread_cond_broadcast(&fCondition); | |
278 } | |
279 | |
280 pthread_mutex_unlock(&fMutex); | |
281 } | |
282 | |
283 private: | |
284 pthread_cond_t fCondition; | |
285 pthread_mutex_t fMutex; | |
286 volatile bool fTriggered; | |
287 | |
288 DISTRHO_PREVENT_HEAP_ALLOCATION | |
289 DISTRHO_DECLARE_NON_COPYABLE(Signal) | |
290 }; | |
291 #endif // _MSC_VER | |
292 | |
293 // ----------------------------------------------------------------------- | |
294 // Helper class to lock&unlock a mutex during a function scope. | |
295 | |
296 template <class Mutex> | |
297 class ScopeLocker | |
298 { | |
299 public: | |
300 ScopeLocker(const Mutex& mutex) noexcept | |
301 : fMutex(mutex) | |
302 { | |
303 fMutex.lock(); | |
304 } | |
305 | |
306 ~ScopeLocker() noexcept | |
307 { | |
308 fMutex.unlock(); | |
309 } | |
310 | |
311 private: | |
312 const Mutex& fMutex; | |
313 | |
314 DISTRHO_PREVENT_HEAP_ALLOCATION | |
315 DISTRHO_DECLARE_NON_COPYABLE(ScopeLocker) | |
316 }; | |
317 | |
318 // ----------------------------------------------------------------------- | |
319 // Helper class to try-lock&unlock a mutex during a function scope. | |
320 | |
321 template <class Mutex> | |
322 class ScopeTryLocker | |
323 { | |
324 public: | |
325 ScopeTryLocker(const Mutex& mutex) noexcept | |
326 : fMutex(mutex), | |
327 fLocked(mutex.tryLock()) {} | |
328 | |
329 ScopeTryLocker(const Mutex& mutex, const bool forceLock) noexcept | |
330 : fMutex(mutex), | |
331 fLocked(forceLock ? mutex.lock() : mutex.tryLock()) {} | |
332 | |
333 ~ScopeTryLocker() noexcept | |
334 { | |
335 if (fLocked) | |
336 fMutex.unlock(); | |
337 } | |
338 | |
339 bool wasLocked() const noexcept | |
340 { | |
341 return fLocked; | |
342 } | |
343 | |
344 bool wasNotLocked() const noexcept | |
345 { | |
346 return !fLocked; | |
347 } | |
348 | |
349 private: | |
350 const Mutex& fMutex; | |
351 const bool fLocked; | |
352 | |
353 DISTRHO_PREVENT_HEAP_ALLOCATION | |
354 DISTRHO_DECLARE_NON_COPYABLE(ScopeTryLocker) | |
355 }; | |
356 | |
357 // ----------------------------------------------------------------------- | |
358 // Helper class to unlock&lock a mutex during a function scope. | |
359 | |
360 template <class Mutex> | |
361 class ScopeUnlocker | |
362 { | |
363 public: | |
364 ScopeUnlocker(const Mutex& mutex) noexcept | |
365 : fMutex(mutex) | |
366 { | |
367 fMutex.unlock(); | |
368 } | |
369 | |
370 ~ScopeUnlocker() noexcept | |
371 { | |
372 fMutex.lock(); | |
373 } | |
374 | |
375 private: | |
376 const Mutex& fMutex; | |
377 | |
378 DISTRHO_PREVENT_HEAP_ALLOCATION | |
379 DISTRHO_DECLARE_NON_COPYABLE(ScopeUnlocker) | |
380 }; | |
381 | |
382 // ----------------------------------------------------------------------- | |
383 // Define types | |
384 | |
385 typedef ScopeLocker<Mutex> MutexLocker; | |
386 typedef ScopeLocker<RecursiveMutex> RecursiveMutexLocker; | |
387 | |
388 typedef ScopeTryLocker<Mutex> MutexTryLocker; | |
389 typedef ScopeTryLocker<RecursiveMutex> RecursiveMutexTryLocker; | |
390 | |
391 typedef ScopeUnlocker<Mutex> MutexUnlocker; | |
392 typedef ScopeUnlocker<RecursiveMutex> RecursiveMutexUnlocker; | |
393 | |
394 // ----------------------------------------------------------------------- | |
395 | |
396 END_NAMESPACE_DISTRHO | |
397 | |
398 #endif // DISTRHO_MUTEX_HPP_INCLUDED |