SDL 3.0
SDL_mutex.h
Go to the documentation of this file.
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22#ifndef SDL_mutex_h_
23#define SDL_mutex_h_
24
25/**
26 * \file SDL_mutex.h
27 *
28 * \brief Functions to provide thread synchronization primitives.
29 */
30
31#include <SDL3/SDL_stdinc.h>
32#include <SDL3/SDL_error.h>
33
34/******************************************************************************/
35/* Enable thread safety attributes only with clang.
36 * The attributes can be safely erased when compiling with other compilers.
37 */
38#if defined(SDL_THREAD_SAFETY_ANALYSIS) && \
39 defined(__clang__) && (!defined(SWIG))
40#define SDL_THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
41#else
42#define SDL_THREAD_ANNOTATION_ATTRIBUTE__(x) /* no-op */
43#endif
44
45#define SDL_CAPABILITY(x) \
46 SDL_THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
47
48#define SDL_SCOPED_CAPABILITY \
49 SDL_THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
50
51#define SDL_GUARDED_BY(x) \
52 SDL_THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
53
54#define SDL_PT_GUARDED_BY(x) \
55 SDL_THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
56
57#define SDL_ACQUIRED_BEFORE(...) \
58 SDL_THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
59
60#define SDL_ACQUIRED_AFTER(...) \
61 SDL_THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
62
63#define SDL_REQUIRES(...) \
64 SDL_THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__))
65
66#define SDL_REQUIRES_SHARED(...) \
67 SDL_THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__))
68
69#define SDL_ACQUIRE(...) \
70 SDL_THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__))
71
72#define SDL_ACQUIRE_SHARED(...) \
73 SDL_THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__))
74
75#define SDL_RELEASE(...) \
76 SDL_THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__))
77
78#define SDL_RELEASE_SHARED(...) \
79 SDL_THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__))
80
81#define SDL_RELEASE_GENERIC(...) \
82 SDL_THREAD_ANNOTATION_ATTRIBUTE__(release_generic_capability(__VA_ARGS__))
83
84#define SDL_TRY_ACQUIRE(...) \
85 SDL_THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__))
86
87#define SDL_TRY_ACQUIRE_SHARED(...) \
88 SDL_THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__))
89
90#define SDL_EXCLUDES(...) \
91 SDL_THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
92
93#define SDL_ASSERT_CAPABILITY(x) \
94 SDL_THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))
95
96#define SDL_ASSERT_SHARED_CAPABILITY(x) \
97 SDL_THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x))
98
99#define SDL_RETURN_CAPABILITY(x) \
100 SDL_THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
101
102#define SDL_NO_THREAD_SAFETY_ANALYSIS \
103 SDL_THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
104
105/******************************************************************************/
106
107
108#include <SDL3/SDL_begin_code.h>
109/* Set up for C function definitions, even when using C++ */
110#ifdef __cplusplus
111extern "C" {
112#endif
113
114/**
115 * Synchronization functions which can time out return this value
116 * if they time out.
117 */
118#define SDL_MUTEX_TIMEDOUT 1
119
120/**
121 * This is the timeout value which corresponds to never time out.
122 */
123#define SDL_MUTEX_MAXWAIT -1
124
125
126/**
127 * \name Mutex functions
128 */
129/* @{ */
130
131/* The SDL mutex structure, defined in SDL_sysmutex.c */
132struct SDL_mutex;
133typedef struct SDL_mutex SDL_mutex;
134
135/**
136 * Create a new mutex.
137 *
138 * All newly-created mutexes begin in the _unlocked_ state.
139 *
140 * Calls to SDL_LockMutex() will not return while the mutex is locked by
141 * another thread. See SDL_TryLockMutex() to attempt to lock without blocking.
142 *
143 * SDL mutexes are reentrant.
144 *
145 * \returns the initialized and unlocked mutex or NULL on failure; call
146 * SDL_GetError() for more information.
147 *
148 * \since This function is available since SDL 3.0.0.
149 *
150 * \sa SDL_DestroyMutex
151 * \sa SDL_LockMutex
152 * \sa SDL_TryLockMutex
153 * \sa SDL_UnlockMutex
154 */
155extern DECLSPEC SDL_mutex *SDLCALL SDL_CreateMutex(void);
156
157/**
158 * Lock the mutex.
159 *
160 * This will block until the mutex is available, which is to say it is in the
161 * unlocked state and the OS has chosen the caller as the next thread to lock
162 * it. Of all threads waiting to lock the mutex, only one may do so at a time.
163 *
164 * It is legal for the owning thread to lock an already-locked mutex. It must
165 * unlock it the same number of times before it is actually made available for
166 * other threads in the system (this is known as a "recursive mutex").
167 *
168 * \param mutex the mutex to lock
169 * \returns 0 on success or a negative error code on failure; call
170 * SDL_GetError() for more information.
171 *
172 * \since This function is available since SDL 3.0.0.
173 */
174extern DECLSPEC int SDLCALL SDL_LockMutex(SDL_mutex * mutex) SDL_ACQUIRE(mutex);
175#define SDL_mutexP(m) SDL_LockMutex(m)
176
177/**
178 * Try to lock a mutex without blocking.
179 *
180 * This works just like SDL_LockMutex(), but if the mutex is not available,
181 * this function returns `SDL_MUTEX_TIMEOUT` immediately.
182 *
183 * This technique is useful if you need exclusive access to a resource but
184 * don't want to wait for it, and will return to it to try again later.
185 *
186 * \param mutex the mutex to try to lock
187 * \returns 0, `SDL_MUTEX_TIMEDOUT`, or -1 on error; call SDL_GetError() for
188 * more information.
189 *
190 * \since This function is available since SDL 3.0.0.
191 *
192 * \sa SDL_CreateMutex
193 * \sa SDL_DestroyMutex
194 * \sa SDL_LockMutex
195 * \sa SDL_UnlockMutex
196 */
197extern DECLSPEC int SDLCALL SDL_TryLockMutex(SDL_mutex * mutex) SDL_TRY_ACQUIRE(0, mutex);
198
199/**
200 * Unlock the mutex.
201 *
202 * It is legal for the owning thread to lock an already-locked mutex. It must
203 * unlock it the same number of times before it is actually made available for
204 * other threads in the system (this is known as a "recursive mutex").
205 *
206 * It is an error to unlock a mutex that has not been locked by the current
207 * thread, and doing so results in undefined behavior.
208 *
209 * It is also an error to unlock a mutex that isn't locked at all.
210 *
211 * \param mutex the mutex to unlock.
212 * \returns 0 on success or a negative error code on failure; call
213 * SDL_GetError() for more information.
214 *
215 * \since This function is available since SDL 3.0.0.
216 */
217extern DECLSPEC int SDLCALL SDL_UnlockMutex(SDL_mutex * mutex) SDL_RELEASE(mutex);
218#define SDL_mutexV(m) SDL_UnlockMutex(m)
219
220/**
221 * Destroy a mutex created with SDL_CreateMutex().
222 *
223 * This function must be called on any mutex that is no longer needed. Failure
224 * to destroy a mutex will result in a system memory or resource leak. While
225 * it is safe to destroy a mutex that is _unlocked_, it is not safe to attempt
226 * to destroy a locked mutex, and may result in undefined behavior depending
227 * on the platform.
228 *
229 * \param mutex the mutex to destroy
230 *
231 * \since This function is available since SDL 3.0.0.
232 *
233 * \sa SDL_CreateMutex
234 * \sa SDL_LockMutex
235 * \sa SDL_TryLockMutex
236 * \sa SDL_UnlockMutex
237 */
238extern DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_mutex * mutex);
239
240/* @} *//* Mutex functions */
241
242
243/**
244 * \name Semaphore functions
245 */
246/* @{ */
247
248/* The SDL semaphore structure, defined in SDL_syssem.c */
249struct SDL_semaphore;
250typedef struct SDL_semaphore SDL_sem;
251
252/**
253 * Create a semaphore.
254 *
255 * This function creates a new semaphore and initializes it with the value
256 * `initial_value`. Each wait operation on the semaphore will atomically
257 * decrement the semaphore value and potentially block if the semaphore value
258 * is 0. Each post operation will atomically increment the semaphore value and
259 * wake waiting threads and allow them to retry the wait operation.
260 *
261 * \param initial_value the starting value of the semaphore
262 * \returns a new semaphore or NULL on failure; call SDL_GetError() for more
263 * information.
264 *
265 * \since This function is available since SDL 3.0.0.
266 *
267 * \sa SDL_DestroySemaphore
268 * \sa SDL_SemPost
269 * \sa SDL_SemTryWait
270 * \sa SDL_SemValue
271 * \sa SDL_SemWait
272 * \sa SDL_SemWaitTimeout
273 */
274extern DECLSPEC SDL_sem *SDLCALL SDL_CreateSemaphore(Uint32 initial_value);
275
276/**
277 * Destroy a semaphore.
278 *
279 * It is not safe to destroy a semaphore if there are threads currently
280 * waiting on it.
281 *
282 * \param sem the semaphore to destroy
283 *
284 * \since This function is available since SDL 3.0.0.
285 *
286 * \sa SDL_CreateSemaphore
287 * \sa SDL_SemPost
288 * \sa SDL_SemTryWait
289 * \sa SDL_SemValue
290 * \sa SDL_SemWait
291 * \sa SDL_SemWaitTimeout
292 */
293extern DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_sem *sem);
294
295/**
296 * Wait until a semaphore has a positive value and then decrements it.
297 *
298 * This function suspends the calling thread until either the semaphore
299 * pointed to by `sem` has a positive value or the call is interrupted by a
300 * signal or error. If the call is successful it will atomically decrement the
301 * semaphore value.
302 *
303 * This function is the equivalent of calling SDL_SemWaitTimeout() with a time
304 * length of `SDL_MUTEX_MAXWAIT`.
305 *
306 * \param sem the semaphore wait on
307 * \returns 0 on success or a negative error code on failure; call
308 * SDL_GetError() for more information.
309 *
310 * \since This function is available since SDL 3.0.0.
311 *
312 * \sa SDL_CreateSemaphore
313 * \sa SDL_DestroySemaphore
314 * \sa SDL_SemPost
315 * \sa SDL_SemTryWait
316 * \sa SDL_SemValue
317 * \sa SDL_SemWait
318 * \sa SDL_SemWaitTimeout
319 */
320extern DECLSPEC int SDLCALL SDL_SemWait(SDL_sem *sem);
321
322/**
323 * See if a semaphore has a positive value and decrement it if it does.
324 *
325 * This function checks to see if the semaphore pointed to by `sem` has a
326 * positive value and atomically decrements the semaphore value if it does. If
327 * the semaphore doesn't have a positive value, the function immediately
328 * returns SDL_MUTEX_TIMEDOUT.
329 *
330 * \param sem the semaphore to wait on
331 * \returns 0 if the wait succeeds, `SDL_MUTEX_TIMEDOUT` if the wait would
332 * block, or a negative error code on failure; call SDL_GetError()
333 * for more information.
334 *
335 * \since This function is available since SDL 3.0.0.
336 *
337 * \sa SDL_CreateSemaphore
338 * \sa SDL_DestroySemaphore
339 * \sa SDL_SemPost
340 * \sa SDL_SemValue
341 * \sa SDL_SemWait
342 * \sa SDL_SemWaitTimeout
343 */
344extern DECLSPEC int SDLCALL SDL_SemTryWait(SDL_sem *sem);
345
346/**
347 * Wait until a semaphore has a positive value and then decrements it.
348 *
349 * This function suspends the calling thread until either the semaphore
350 * pointed to by `sem` has a positive value, the call is interrupted by a
351 * signal or error, or the specified time has elapsed. If the call is
352 * successful it will atomically decrement the semaphore value.
353 *
354 * \param sem the semaphore to wait on
355 * \param timeoutMS the length of the timeout, in milliseconds
356 * \returns 0 if the wait succeeds, `SDL_MUTEX_TIMEDOUT` if the wait does not
357 * succeed in the allotted time, or a negative error code on failure;
358 * call SDL_GetError() for more information.
359 *
360 * \since This function is available since SDL 3.0.0.
361 *
362 * \sa SDL_CreateSemaphore
363 * \sa SDL_DestroySemaphore
364 * \sa SDL_SemPost
365 * \sa SDL_SemTryWait
366 * \sa SDL_SemValue
367 * \sa SDL_SemWait
368 */
369extern DECLSPEC int SDLCALL SDL_SemWaitTimeout(SDL_sem *sem, Sint32 timeoutMS);
370
371/**
372 * Atomically increment a semaphore's value and wake waiting threads.
373 *
374 * \param sem the semaphore to increment
375 * \returns 0 on success or a negative error code on failure; call
376 * SDL_GetError() for more information.
377 *
378 * \since This function is available since SDL 3.0.0.
379 *
380 * \sa SDL_CreateSemaphore
381 * \sa SDL_DestroySemaphore
382 * \sa SDL_SemTryWait
383 * \sa SDL_SemValue
384 * \sa SDL_SemWait
385 * \sa SDL_SemWaitTimeout
386 */
387extern DECLSPEC int SDLCALL SDL_SemPost(SDL_sem *sem);
388
389/**
390 * Get the current value of a semaphore.
391 *
392 * \param sem the semaphore to query
393 * \returns the current value of the semaphore.
394 *
395 * \since This function is available since SDL 3.0.0.
396 *
397 * \sa SDL_CreateSemaphore
398 */
399extern DECLSPEC Uint32 SDLCALL SDL_SemValue(SDL_sem *sem);
400
401/* @} *//* Semaphore functions */
402
403
404/**
405 * \name Condition variable functions
406 */
407/* @{ */
408
409/* The SDL condition variable structure, defined in SDL_syscond.c */
410struct SDL_cond;
411typedef struct SDL_cond SDL_cond;
412
413/**
414 * Create a condition variable.
415 *
416 * \returns a new condition variable or NULL on failure; call SDL_GetError()
417 * for more information.
418 *
419 * \since This function is available since SDL 3.0.0.
420 *
421 * \sa SDL_CondBroadcast
422 * \sa SDL_CondSignal
423 * \sa SDL_CondWait
424 * \sa SDL_CondWaitTimeout
425 * \sa SDL_DestroyCond
426 */
427extern DECLSPEC SDL_cond *SDLCALL SDL_CreateCond(void);
428
429/**
430 * Destroy a condition variable.
431 *
432 * \param cond the condition variable to destroy
433 *
434 * \since This function is available since SDL 3.0.0.
435 *
436 * \sa SDL_CondBroadcast
437 * \sa SDL_CondSignal
438 * \sa SDL_CondWait
439 * \sa SDL_CondWaitTimeout
440 * \sa SDL_CreateCond
441 */
442extern DECLSPEC void SDLCALL SDL_DestroyCond(SDL_cond *cond);
443
444/**
445 * Restart one of the threads that are waiting on the condition variable.
446 *
447 * \param cond the condition variable to signal
448 * \returns 0 on success or a negative error code on failure; call
449 * SDL_GetError() for more information.
450 *
451 * \since This function is available since SDL 3.0.0.
452 *
453 * \sa SDL_CondBroadcast
454 * \sa SDL_CondWait
455 * \sa SDL_CondWaitTimeout
456 * \sa SDL_CreateCond
457 * \sa SDL_DestroyCond
458 */
459extern DECLSPEC int SDLCALL SDL_CondSignal(SDL_cond *cond);
460
461/**
462 * Restart all threads that are waiting on the condition variable.
463 *
464 * \param cond the condition variable to signal
465 * \returns 0 on success or a negative error code on failure; call
466 * SDL_GetError() for more information.
467 *
468 * \since This function is available since SDL 3.0.0.
469 *
470 * \sa SDL_CondSignal
471 * \sa SDL_CondWait
472 * \sa SDL_CondWaitTimeout
473 * \sa SDL_CreateCond
474 * \sa SDL_DestroyCond
475 */
476extern DECLSPEC int SDLCALL SDL_CondBroadcast(SDL_cond *cond);
477
478/**
479 * Wait until a condition variable is signaled.
480 *
481 * This function unlocks the specified `mutex` and waits for another thread to
482 * call SDL_CondSignal() or SDL_CondBroadcast() on the condition variable
483 * `cond`. Once the condition variable is signaled, the mutex is re-locked and
484 * the function returns.
485 *
486 * The mutex must be locked before calling this function. Locking the mutex
487 * recursively (more than once) is not supported and leads to undefined
488 * behavior.
489 *
490 * This function is the equivalent of calling SDL_CondWaitTimeout() with a
491 * time length of `SDL_MUTEX_MAXWAIT`.
492 *
493 * \param cond the condition variable to wait on
494 * \param mutex the mutex used to coordinate thread access
495 * \returns 0 when it is signaled or a negative error code on failure; call
496 * SDL_GetError() for more information.
497 *
498 * \since This function is available since SDL 3.0.0.
499 *
500 * \sa SDL_CondBroadcast
501 * \sa SDL_CondSignal
502 * \sa SDL_CondWaitTimeout
503 * \sa SDL_CreateCond
504 * \sa SDL_DestroyCond
505 */
506extern DECLSPEC int SDLCALL SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex);
507
508/**
509 * Wait until a condition variable is signaled or a certain time has passed.
510 *
511 * This function unlocks the specified `mutex` and waits for another thread to
512 * call SDL_CondSignal() or SDL_CondBroadcast() on the condition variable
513 * `cond`, or for the specified time to elapse. Once the condition variable is
514 * signaled or the time elapsed, the mutex is re-locked and the function
515 * returns.
516 *
517 * The mutex must be locked before calling this function. Locking the mutex
518 * recursively (more than once) is not supported and leads to undefined
519 * behavior.
520 *
521 * \param cond the condition variable to wait on
522 * \param mutex the mutex used to coordinate thread access
523 * \param timeoutMS the maximum time to wait, in milliseconds, or
524 * `SDL_MUTEX_MAXWAIT` to wait indefinitely
525 * \returns 0 if the condition variable is signaled, `SDL_MUTEX_TIMEDOUT` if
526 * the condition is not signaled in the allotted time, or a negative
527 * error code on failure; call SDL_GetError() for more information.
528 *
529 * \since This function is available since SDL 3.0.0.
530 *
531 * \sa SDL_CondBroadcast
532 * \sa SDL_CondSignal
533 * \sa SDL_CondWait
534 * \sa SDL_CreateCond
535 * \sa SDL_DestroyCond
536 */
537extern DECLSPEC int SDLCALL SDL_CondWaitTimeout(SDL_cond *cond,
538 SDL_mutex *mutex, Sint32 timeoutMS);
539
540/* @} *//* Condition variable functions */
541
542
543/* Ends C function definitions when using C++ */
544#ifdef __cplusplus
545}
546#endif
547#include <SDL3/SDL_close_code.h>
548
549#endif /* SDL_mutex_h_ */
int SDL_SemWait(SDL_sem *sem)
int SDL_TryLockMutex(SDL_mutex *mutex) SDL_TRY_ACQUIRE(0
void SDL_DestroyMutex(SDL_mutex *mutex)
SDL_cond * SDL_CreateCond(void)
SDL_sem * SDL_CreateSemaphore(Uint32 initial_value)
void SDL_DestroySemaphore(SDL_sem *sem)
int SDL_SemWaitTimeout(SDL_sem *sem, Sint32 timeoutMS)
#define SDL_TRY_ACQUIRE(...)
Definition: SDL_mutex.h:84
#define SDL_ACQUIRE(...)
Definition: SDL_mutex.h:69
int SDL_CondBroadcast(SDL_cond *cond)
int mutex
Definition: SDL_mutex.h:197
int SDL_SemPost(SDL_sem *sem)
int SDL_CondSignal(SDL_cond *cond)
void SDL_DestroyCond(SDL_cond *cond)
int SDL_UnlockMutex(SDL_mutex *mutex) SDL_RELEASE(mutex)
#define SDL_RELEASE(...)
Definition: SDL_mutex.h:75
struct SDL_semaphore SDL_sem
Definition: SDL_mutex.h:250
int SDL_LockMutex(SDL_mutex *mutex) SDL_ACQUIRE(mutex)
int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Sint32 timeoutMS)
struct SDL_mutex SDL_mutex
Definition: SDL_mutex.h:133
struct SDL_cond SDL_cond
Definition: SDL_mutex.h:411
SDL_mutex * SDL_CreateMutex(void)
Uint32 SDL_SemValue(SDL_sem *sem)
int SDL_SemTryWait(SDL_sem *sem)
int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
This is a general header that includes C language support.
int32_t Sint32
Definition: SDL_stdinc.h:165
uint32_t Uint32
Definition: SDL_stdinc.h:171