|
1
|
1 /*
|
|
|
2 Simple DirectMedia Layer
|
|
|
3 Copyright (C) 1997-2025 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 * # CategoryMutex
|
|
|
27 *
|
|
|
28 * SDL offers several thread synchronization primitives. This document can't
|
|
|
29 * cover the complicated topic of thread safety, but reading up on what each
|
|
|
30 * of these primitives are, why they are useful, and how to correctly use them
|
|
|
31 * is vital to writing correct and safe multithreaded programs.
|
|
|
32 *
|
|
|
33 * - Mutexes: SDL_CreateMutex()
|
|
|
34 * - Read/Write locks: SDL_CreateRWLock()
|
|
|
35 * - Semaphores: SDL_CreateSemaphore()
|
|
|
36 * - Condition variables: SDL_CreateCondition()
|
|
|
37 *
|
|
|
38 * SDL also offers a datatype, SDL_InitState, which can be used to make sure
|
|
|
39 * only one thread initializes/deinitializes some resource that several
|
|
|
40 * threads might try to use for the first time simultaneously.
|
|
|
41 */
|
|
|
42
|
|
|
43 #include <SDL3/SDL_stdinc.h>
|
|
|
44 #include <SDL3/SDL_atomic.h>
|
|
|
45 #include <SDL3/SDL_error.h>
|
|
|
46 #include <SDL3/SDL_thread.h>
|
|
|
47
|
|
|
48 #ifdef SDL_WIKI_DOCUMENTATION_SECTION
|
|
|
49
|
|
|
50 /**
|
|
|
51 * Enable thread safety attributes, only with clang.
|
|
|
52 *
|
|
|
53 * The attributes can be safely erased when compiling with other compilers.
|
|
|
54 *
|
|
|
55 * To enable analysis, set these environment variables before running cmake:
|
|
|
56 *
|
|
|
57 * ```bash
|
|
|
58 * export CC=clang
|
|
|
59 * export CFLAGS="-DSDL_THREAD_SAFETY_ANALYSIS -Wthread-safety"
|
|
|
60 * ```
|
|
|
61 */
|
|
|
62 #define SDL_THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
|
|
|
63
|
|
|
64 #elif defined(SDL_THREAD_SAFETY_ANALYSIS) && defined(__clang__) && (!defined(SWIG))
|
|
|
65 #define SDL_THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
|
|
|
66 #else
|
|
|
67 #define SDL_THREAD_ANNOTATION_ATTRIBUTE__(x) /* no-op */
|
|
|
68 #endif
|
|
|
69
|
|
|
70 /**
|
|
|
71 * Wrapper around Clang thread safety analysis annotations.
|
|
|
72 *
|
|
|
73 * Please see https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutex-h
|
|
|
74 *
|
|
|
75 * \since This macro is available since SDL 3.2.0.
|
|
|
76 */
|
|
|
77 #define SDL_CAPABILITY(x) \
|
|
|
78 SDL_THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
|
|
|
79
|
|
|
80 /**
|
|
|
81 * Wrapper around Clang thread safety analysis annotations.
|
|
|
82 *
|
|
|
83 * Please see https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutex-h
|
|
|
84 *
|
|
|
85 * \since This macro is available since SDL 3.2.0.
|
|
|
86 */
|
|
|
87 #define SDL_SCOPED_CAPABILITY \
|
|
|
88 SDL_THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
|
|
|
89
|
|
|
90 /**
|
|
|
91 * Wrapper around Clang thread safety analysis annotations.
|
|
|
92 *
|
|
|
93 * Please see https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutex-h
|
|
|
94 *
|
|
|
95 * \since This macro is available since SDL 3.2.0.
|
|
|
96 */
|
|
|
97 #define SDL_GUARDED_BY(x) \
|
|
|
98 SDL_THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
|
|
|
99
|
|
|
100 /**
|
|
|
101 * Wrapper around Clang thread safety analysis annotations.
|
|
|
102 *
|
|
|
103 * Please see https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutex-h
|
|
|
104 *
|
|
|
105 * \since This macro is available since SDL 3.2.0.
|
|
|
106 */
|
|
|
107 #define SDL_PT_GUARDED_BY(x) \
|
|
|
108 SDL_THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
|
|
|
109
|
|
|
110 /**
|
|
|
111 * Wrapper around Clang thread safety analysis annotations.
|
|
|
112 *
|
|
|
113 * Please see https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutex-h
|
|
|
114 *
|
|
|
115 * \since This macro is available since SDL 3.2.0.
|
|
|
116 */
|
|
|
117 #define SDL_ACQUIRED_BEFORE(x) \
|
|
|
118 SDL_THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(x))
|
|
|
119
|
|
|
120 /**
|
|
|
121 * Wrapper around Clang thread safety analysis annotations.
|
|
|
122 *
|
|
|
123 * Please see https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutex-h
|
|
|
124 *
|
|
|
125 * \since This macro is available since SDL 3.2.0.
|
|
|
126 */
|
|
|
127 #define SDL_ACQUIRED_AFTER(x) \
|
|
|
128 SDL_THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(x))
|
|
|
129
|
|
|
130 /**
|
|
|
131 * Wrapper around Clang thread safety analysis annotations.
|
|
|
132 *
|
|
|
133 * Please see https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutex-h
|
|
|
134 *
|
|
|
135 * \since This macro is available since SDL 3.2.0.
|
|
|
136 */
|
|
|
137 #define SDL_REQUIRES(x) \
|
|
|
138 SDL_THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(x))
|
|
|
139
|
|
|
140 /**
|
|
|
141 * Wrapper around Clang thread safety analysis annotations.
|
|
|
142 *
|
|
|
143 * Please see https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutex-h
|
|
|
144 *
|
|
|
145 * \since This macro is available since SDL 3.2.0.
|
|
|
146 */
|
|
|
147 #define SDL_REQUIRES_SHARED(x) \
|
|
|
148 SDL_THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(x))
|
|
|
149
|
|
|
150 /**
|
|
|
151 * Wrapper around Clang thread safety analysis annotations.
|
|
|
152 *
|
|
|
153 * Please see https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutex-h
|
|
|
154 *
|
|
|
155 * \since This macro is available since SDL 3.2.0.
|
|
|
156 */
|
|
|
157 #define SDL_ACQUIRE(x) \
|
|
|
158 SDL_THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(x))
|
|
|
159
|
|
|
160 /**
|
|
|
161 * Wrapper around Clang thread safety analysis annotations.
|
|
|
162 *
|
|
|
163 * Please see https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutex-h
|
|
|
164 *
|
|
|
165 * \since This macro is available since SDL 3.2.0.
|
|
|
166 */
|
|
|
167 #define SDL_ACQUIRE_SHARED(x) \
|
|
|
168 SDL_THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(x))
|
|
|
169
|
|
|
170 /**
|
|
|
171 * Wrapper around Clang thread safety analysis annotations.
|
|
|
172 *
|
|
|
173 * Please see https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutex-h
|
|
|
174 *
|
|
|
175 * \since This macro is available since SDL 3.2.0.
|
|
|
176 */
|
|
|
177 #define SDL_RELEASE(x) \
|
|
|
178 SDL_THREAD_ANNOTATION_ATTRIBUTE__(release_capability(x))
|
|
|
179
|
|
|
180 /**
|
|
|
181 * Wrapper around Clang thread safety analysis annotations.
|
|
|
182 *
|
|
|
183 * Please see https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutex-h
|
|
|
184 *
|
|
|
185 * \since This macro is available since SDL 3.2.0.
|
|
|
186 */
|
|
|
187 #define SDL_RELEASE_SHARED(x) \
|
|
|
188 SDL_THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(x))
|
|
|
189
|
|
|
190 /**
|
|
|
191 * Wrapper around Clang thread safety analysis annotations.
|
|
|
192 *
|
|
|
193 * Please see https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutex-h
|
|
|
194 *
|
|
|
195 * \since This macro is available since SDL 3.2.0.
|
|
|
196 */
|
|
|
197 #define SDL_RELEASE_GENERIC(x) \
|
|
|
198 SDL_THREAD_ANNOTATION_ATTRIBUTE__(release_generic_capability(x))
|
|
|
199
|
|
|
200 /**
|
|
|
201 * Wrapper around Clang thread safety analysis annotations.
|
|
|
202 *
|
|
|
203 * Please see https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutex-h
|
|
|
204 *
|
|
|
205 * \since This macro is available since SDL 3.2.0.
|
|
|
206 */
|
|
|
207 #define SDL_TRY_ACQUIRE(x, y) \
|
|
|
208 SDL_THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(x, y))
|
|
|
209
|
|
|
210 /**
|
|
|
211 * Wrapper around Clang thread safety analysis annotations.
|
|
|
212 *
|
|
|
213 * Please see https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutex-h
|
|
|
214 *
|
|
|
215 * \since This macro is available since SDL 3.2.0.
|
|
|
216 */
|
|
|
217 #define SDL_TRY_ACQUIRE_SHARED(x, y) \
|
|
|
218 SDL_THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(x, y))
|
|
|
219
|
|
|
220 /**
|
|
|
221 * Wrapper around Clang thread safety analysis annotations.
|
|
|
222 *
|
|
|
223 * Please see https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutex-h
|
|
|
224 *
|
|
|
225 * \since This macro is available since SDL 3.2.0.
|
|
|
226 */
|
|
|
227 #define SDL_EXCLUDES(x) \
|
|
|
228 SDL_THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(x))
|
|
|
229
|
|
|
230 /**
|
|
|
231 * Wrapper around Clang thread safety analysis annotations.
|
|
|
232 *
|
|
|
233 * Please see https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutex-h
|
|
|
234 *
|
|
|
235 * \since This macro is available since SDL 3.2.0.
|
|
|
236 */
|
|
|
237 #define SDL_ASSERT_CAPABILITY(x) \
|
|
|
238 SDL_THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))
|
|
|
239
|
|
|
240 /**
|
|
|
241 * Wrapper around Clang thread safety analysis annotations.
|
|
|
242 *
|
|
|
243 * Please see https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutex-h
|
|
|
244 *
|
|
|
245 * \since This macro is available since SDL 3.2.0.
|
|
|
246 */
|
|
|
247 #define SDL_ASSERT_SHARED_CAPABILITY(x) \
|
|
|
248 SDL_THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x))
|
|
|
249
|
|
|
250 /**
|
|
|
251 * Wrapper around Clang thread safety analysis annotations.
|
|
|
252 *
|
|
|
253 * Please see https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutex-h
|
|
|
254 *
|
|
|
255 * \since This macro is available since SDL 3.2.0.
|
|
|
256 */
|
|
|
257 #define SDL_RETURN_CAPABILITY(x) \
|
|
|
258 SDL_THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
|
|
|
259
|
|
|
260 /**
|
|
|
261 * Wrapper around Clang thread safety analysis annotations.
|
|
|
262 *
|
|
|
263 * Please see https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutex-h
|
|
|
264 *
|
|
|
265 * \since This macro is available since SDL 3.2.0.
|
|
|
266 */
|
|
|
267 #define SDL_NO_THREAD_SAFETY_ANALYSIS \
|
|
|
268 SDL_THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
|
|
|
269
|
|
|
270 /******************************************************************************/
|
|
|
271
|
|
|
272
|
|
|
273 #include <SDL3/SDL_begin_code.h>
|
|
|
274 /* Set up for C function definitions, even when using C++ */
|
|
|
275 #ifdef __cplusplus
|
|
|
276 extern "C" {
|
|
|
277 #endif
|
|
|
278
|
|
|
279 /**
|
|
|
280 * \name Mutex functions
|
|
|
281 */
|
|
|
282 /* @{ */
|
|
|
283
|
|
|
284 /**
|
|
|
285 * A means to serialize access to a resource between threads.
|
|
|
286 *
|
|
|
287 * Mutexes (short for "mutual exclusion") are a synchronization primitive that
|
|
|
288 * allows exactly one thread to proceed at a time.
|
|
|
289 *
|
|
|
290 * Wikipedia has a thorough explanation of the concept:
|
|
|
291 *
|
|
|
292 * https://en.wikipedia.org/wiki/Mutex
|
|
|
293 *
|
|
|
294 * \since This struct is available since SDL 3.2.0.
|
|
|
295 */
|
|
|
296 typedef struct SDL_Mutex SDL_Mutex;
|
|
|
297
|
|
|
298 /**
|
|
|
299 * Create a new mutex.
|
|
|
300 *
|
|
|
301 * All newly-created mutexes begin in the _unlocked_ state.
|
|
|
302 *
|
|
|
303 * Calls to SDL_LockMutex() will not return while the mutex is locked by
|
|
|
304 * another thread. See SDL_TryLockMutex() to attempt to lock without blocking.
|
|
|
305 *
|
|
|
306 * SDL mutexes are reentrant.
|
|
|
307 *
|
|
|
308 * \returns the initialized and unlocked mutex or NULL on failure; call
|
|
|
309 * SDL_GetError() for more information.
|
|
|
310 *
|
|
|
311 * \since This function is available since SDL 3.2.0.
|
|
|
312 *
|
|
|
313 * \sa SDL_DestroyMutex
|
|
|
314 * \sa SDL_LockMutex
|
|
|
315 * \sa SDL_TryLockMutex
|
|
|
316 * \sa SDL_UnlockMutex
|
|
|
317 */
|
|
|
318 extern SDL_DECLSPEC SDL_Mutex * SDLCALL SDL_CreateMutex(void);
|
|
|
319
|
|
|
320 /**
|
|
|
321 * Lock the mutex.
|
|
|
322 *
|
|
|
323 * This will block until the mutex is available, which is to say it is in the
|
|
|
324 * unlocked state and the OS has chosen the caller as the next thread to lock
|
|
|
325 * it. Of all threads waiting to lock the mutex, only one may do so at a time.
|
|
|
326 *
|
|
|
327 * It is legal for the owning thread to lock an already-locked mutex. It must
|
|
|
328 * unlock it the same number of times before it is actually made available for
|
|
|
329 * other threads in the system (this is known as a "recursive mutex").
|
|
|
330 *
|
|
|
331 * This function does not fail; if mutex is NULL, it will return immediately
|
|
|
332 * having locked nothing. If the mutex is valid, this function will always
|
|
|
333 * block until it can lock the mutex, and return with it locked.
|
|
|
334 *
|
|
|
335 * \param mutex the mutex to lock.
|
|
|
336 *
|
|
|
337 * \since This function is available since SDL 3.2.0.
|
|
|
338 *
|
|
|
339 * \sa SDL_TryLockMutex
|
|
|
340 * \sa SDL_UnlockMutex
|
|
|
341 */
|
|
|
342 extern SDL_DECLSPEC void SDLCALL SDL_LockMutex(SDL_Mutex *mutex) SDL_ACQUIRE(mutex);
|
|
|
343
|
|
|
344 /**
|
|
|
345 * Try to lock a mutex without blocking.
|
|
|
346 *
|
|
|
347 * This works just like SDL_LockMutex(), but if the mutex is not available,
|
|
|
348 * this function returns false immediately.
|
|
|
349 *
|
|
|
350 * This technique is useful if you need exclusive access to a resource but
|
|
|
351 * don't want to wait for it, and will return to it to try again later.
|
|
|
352 *
|
|
|
353 * This function returns true if passed a NULL mutex.
|
|
|
354 *
|
|
|
355 * \param mutex the mutex to try to lock.
|
|
|
356 * \returns true on success, false if the mutex would block.
|
|
|
357 *
|
|
|
358 * \since This function is available since SDL 3.2.0.
|
|
|
359 *
|
|
|
360 * \sa SDL_LockMutex
|
|
|
361 * \sa SDL_UnlockMutex
|
|
|
362 */
|
|
|
363 extern SDL_DECLSPEC bool SDLCALL SDL_TryLockMutex(SDL_Mutex *mutex) SDL_TRY_ACQUIRE(true, mutex);
|
|
|
364
|
|
|
365 /**
|
|
|
366 * Unlock the mutex.
|
|
|
367 *
|
|
|
368 * It is legal for the owning thread to lock an already-locked mutex. It must
|
|
|
369 * unlock it the same number of times before it is actually made available for
|
|
|
370 * other threads in the system (this is known as a "recursive mutex").
|
|
|
371 *
|
|
|
372 * It is illegal to unlock a mutex that has not been locked by the current
|
|
|
373 * thread, and doing so results in undefined behavior.
|
|
|
374 *
|
|
|
375 * \param mutex the mutex to unlock.
|
|
|
376 *
|
|
|
377 * \since This function is available since SDL 3.2.0.
|
|
|
378 *
|
|
|
379 * \sa SDL_LockMutex
|
|
|
380 * \sa SDL_TryLockMutex
|
|
|
381 */
|
|
|
382 extern SDL_DECLSPEC void SDLCALL SDL_UnlockMutex(SDL_Mutex *mutex) SDL_RELEASE(mutex);
|
|
|
383
|
|
|
384 /**
|
|
|
385 * Destroy a mutex created with SDL_CreateMutex().
|
|
|
386 *
|
|
|
387 * This function must be called on any mutex that is no longer needed. Failure
|
|
|
388 * to destroy a mutex will result in a system memory or resource leak. While
|
|
|
389 * it is safe to destroy a mutex that is _unlocked_, it is not safe to attempt
|
|
|
390 * to destroy a locked mutex, and may result in undefined behavior depending
|
|
|
391 * on the platform.
|
|
|
392 *
|
|
|
393 * \param mutex the mutex to destroy.
|
|
|
394 *
|
|
|
395 * \since This function is available since SDL 3.2.0.
|
|
|
396 *
|
|
|
397 * \sa SDL_CreateMutex
|
|
|
398 */
|
|
|
399 extern SDL_DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_Mutex *mutex);
|
|
|
400
|
|
|
401 /* @} *//* Mutex functions */
|
|
|
402
|
|
|
403
|
|
|
404 /**
|
|
|
405 * \name Read/write lock functions
|
|
|
406 */
|
|
|
407 /* @{ */
|
|
|
408
|
|
|
409 /**
|
|
|
410 * A mutex that allows read-only threads to run in parallel.
|
|
|
411 *
|
|
|
412 * A rwlock is roughly the same concept as SDL_Mutex, but allows threads that
|
|
|
413 * request read-only access to all hold the lock at the same time. If a thread
|
|
|
414 * requests write access, it will block until all read-only threads have
|
|
|
415 * released the lock, and no one else can hold the thread (for reading or
|
|
|
416 * writing) at the same time as the writing thread.
|
|
|
417 *
|
|
|
418 * This can be more efficient in cases where several threads need to access
|
|
|
419 * data frequently, but changes to that data are rare.
|
|
|
420 *
|
|
|
421 * There are other rules that apply to rwlocks that don't apply to mutexes,
|
|
|
422 * about how threads are scheduled and when they can be recursively locked.
|
|
|
423 * These are documented in the other rwlock functions.
|
|
|
424 *
|
|
|
425 * \since This struct is available since SDL 3.2.0.
|
|
|
426 */
|
|
|
427 typedef struct SDL_RWLock SDL_RWLock;
|
|
|
428
|
|
|
429 /**
|
|
|
430 * Create a new read/write lock.
|
|
|
431 *
|
|
|
432 * A read/write lock is useful for situations where you have multiple threads
|
|
|
433 * trying to access a resource that is rarely updated. All threads requesting
|
|
|
434 * a read-only lock will be allowed to run in parallel; if a thread requests a
|
|
|
435 * write lock, it will be provided exclusive access. This makes it safe for
|
|
|
436 * multiple threads to use a resource at the same time if they promise not to
|
|
|
437 * change it, and when it has to be changed, the rwlock will serve as a
|
|
|
438 * gateway to make sure those changes can be made safely.
|
|
|
439 *
|
|
|
440 * In the right situation, a rwlock can be more efficient than a mutex, which
|
|
|
441 * only lets a single thread proceed at a time, even if it won't be modifying
|
|
|
442 * the data.
|
|
|
443 *
|
|
|
444 * All newly-created read/write locks begin in the _unlocked_ state.
|
|
|
445 *
|
|
|
446 * Calls to SDL_LockRWLockForReading() and SDL_LockRWLockForWriting will not
|
|
|
447 * return while the rwlock is locked _for writing_ by another thread. See
|
|
|
448 * SDL_TryLockRWLockForReading() and SDL_TryLockRWLockForWriting() to attempt
|
|
|
449 * to lock without blocking.
|
|
|
450 *
|
|
|
451 * SDL read/write locks are only recursive for read-only locks! They are not
|
|
|
452 * guaranteed to be fair, or provide access in a FIFO manner! They are not
|
|
|
453 * guaranteed to favor writers. You may not lock a rwlock for both read-only
|
|
|
454 * and write access at the same time from the same thread (so you can't
|
|
|
455 * promote your read-only lock to a write lock without unlocking first).
|
|
|
456 *
|
|
|
457 * \returns the initialized and unlocked read/write lock or NULL on failure;
|
|
|
458 * call SDL_GetError() for more information.
|
|
|
459 *
|
|
|
460 * \since This function is available since SDL 3.2.0.
|
|
|
461 *
|
|
|
462 * \sa SDL_DestroyRWLock
|
|
|
463 * \sa SDL_LockRWLockForReading
|
|
|
464 * \sa SDL_LockRWLockForWriting
|
|
|
465 * \sa SDL_TryLockRWLockForReading
|
|
|
466 * \sa SDL_TryLockRWLockForWriting
|
|
|
467 * \sa SDL_UnlockRWLock
|
|
|
468 */
|
|
|
469 extern SDL_DECLSPEC SDL_RWLock * SDLCALL SDL_CreateRWLock(void);
|
|
|
470
|
|
|
471 /**
|
|
|
472 * Lock the read/write lock for _read only_ operations.
|
|
|
473 *
|
|
|
474 * This will block until the rwlock is available, which is to say it is not
|
|
|
475 * locked for writing by any other thread. Of all threads waiting to lock the
|
|
|
476 * rwlock, all may do so at the same time as long as they are requesting
|
|
|
477 * read-only access; if a thread wants to lock for writing, only one may do so
|
|
|
478 * at a time, and no other threads, read-only or not, may hold the lock at the
|
|
|
479 * same time.
|
|
|
480 *
|
|
|
481 * It is legal for the owning thread to lock an already-locked rwlock for
|
|
|
482 * reading. It must unlock it the same number of times before it is actually
|
|
|
483 * made available for other threads in the system (this is known as a
|
|
|
484 * "recursive rwlock").
|
|
|
485 *
|
|
|
486 * Note that locking for writing is not recursive (this is only available to
|
|
|
487 * read-only locks).
|
|
|
488 *
|
|
|
489 * It is illegal to request a read-only lock from a thread that already holds
|
|
|
490 * the write lock. Doing so results in undefined behavior. Unlock the write
|
|
|
491 * lock before requesting a read-only lock. (But, of course, if you have the
|
|
|
492 * write lock, you don't need further locks to read in any case.)
|
|
|
493 *
|
|
|
494 * This function does not fail; if rwlock is NULL, it will return immediately
|
|
|
495 * having locked nothing. If the rwlock is valid, this function will always
|
|
|
496 * block until it can lock the mutex, and return with it locked.
|
|
|
497 *
|
|
|
498 * \param rwlock the read/write lock to lock.
|
|
|
499 *
|
|
|
500 * \since This function is available since SDL 3.2.0.
|
|
|
501 *
|
|
|
502 * \sa SDL_LockRWLockForWriting
|
|
|
503 * \sa SDL_TryLockRWLockForReading
|
|
|
504 * \sa SDL_UnlockRWLock
|
|
|
505 */
|
|
|
506 extern SDL_DECLSPEC void SDLCALL SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_ACQUIRE_SHARED(rwlock);
|
|
|
507
|
|
|
508 /**
|
|
|
509 * Lock the read/write lock for _write_ operations.
|
|
|
510 *
|
|
|
511 * This will block until the rwlock is available, which is to say it is not
|
|
|
512 * locked for reading or writing by any other thread. Only one thread may hold
|
|
|
513 * the lock when it requests write access; all other threads, whether they
|
|
|
514 * also want to write or only want read-only access, must wait until the
|
|
|
515 * writer thread has released the lock.
|
|
|
516 *
|
|
|
517 * It is illegal for the owning thread to lock an already-locked rwlock for
|
|
|
518 * writing (read-only may be locked recursively, writing can not). Doing so
|
|
|
519 * results in undefined behavior.
|
|
|
520 *
|
|
|
521 * It is illegal to request a write lock from a thread that already holds a
|
|
|
522 * read-only lock. Doing so results in undefined behavior. Unlock the
|
|
|
523 * read-only lock before requesting a write lock.
|
|
|
524 *
|
|
|
525 * This function does not fail; if rwlock is NULL, it will return immediately
|
|
|
526 * having locked nothing. If the rwlock is valid, this function will always
|
|
|
527 * block until it can lock the mutex, and return with it locked.
|
|
|
528 *
|
|
|
529 * \param rwlock the read/write lock to lock.
|
|
|
530 *
|
|
|
531 * \since This function is available since SDL 3.2.0.
|
|
|
532 *
|
|
|
533 * \sa SDL_LockRWLockForReading
|
|
|
534 * \sa SDL_TryLockRWLockForWriting
|
|
|
535 * \sa SDL_UnlockRWLock
|
|
|
536 */
|
|
|
537 extern SDL_DECLSPEC void SDLCALL SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_ACQUIRE(rwlock);
|
|
|
538
|
|
|
539 /**
|
|
|
540 * Try to lock a read/write lock _for reading_ without blocking.
|
|
|
541 *
|
|
|
542 * This works just like SDL_LockRWLockForReading(), but if the rwlock is not
|
|
|
543 * available, then this function returns false immediately.
|
|
|
544 *
|
|
|
545 * This technique is useful if you need access to a resource but don't want to
|
|
|
546 * wait for it, and will return to it to try again later.
|
|
|
547 *
|
|
|
548 * Trying to lock for read-only access can succeed if other threads are
|
|
|
549 * holding read-only locks, as this won't prevent access.
|
|
|
550 *
|
|
|
551 * This function returns true if passed a NULL rwlock.
|
|
|
552 *
|
|
|
553 * \param rwlock the rwlock to try to lock.
|
|
|
554 * \returns true on success, false if the lock would block.
|
|
|
555 *
|
|
|
556 * \since This function is available since SDL 3.2.0.
|
|
|
557 *
|
|
|
558 * \sa SDL_LockRWLockForReading
|
|
|
559 * \sa SDL_TryLockRWLockForWriting
|
|
|
560 * \sa SDL_UnlockRWLock
|
|
|
561 */
|
|
|
562 extern SDL_DECLSPEC bool SDLCALL SDL_TryLockRWLockForReading(SDL_RWLock *rwlock) SDL_TRY_ACQUIRE_SHARED(true, rwlock);
|
|
|
563
|
|
|
564 /**
|
|
|
565 * Try to lock a read/write lock _for writing_ without blocking.
|
|
|
566 *
|
|
|
567 * This works just like SDL_LockRWLockForWriting(), but if the rwlock is not
|
|
|
568 * available, then this function returns false immediately.
|
|
|
569 *
|
|
|
570 * This technique is useful if you need exclusive access to a resource but
|
|
|
571 * don't want to wait for it, and will return to it to try again later.
|
|
|
572 *
|
|
|
573 * It is illegal for the owning thread to lock an already-locked rwlock for
|
|
|
574 * writing (read-only may be locked recursively, writing can not). Doing so
|
|
|
575 * results in undefined behavior.
|
|
|
576 *
|
|
|
577 * It is illegal to request a write lock from a thread that already holds a
|
|
|
578 * read-only lock. Doing so results in undefined behavior. Unlock the
|
|
|
579 * read-only lock before requesting a write lock.
|
|
|
580 *
|
|
|
581 * This function returns true if passed a NULL rwlock.
|
|
|
582 *
|
|
|
583 * \param rwlock the rwlock to try to lock.
|
|
|
584 * \returns true on success, false if the lock would block.
|
|
|
585 *
|
|
|
586 * \since This function is available since SDL 3.2.0.
|
|
|
587 *
|
|
|
588 * \sa SDL_LockRWLockForWriting
|
|
|
589 * \sa SDL_TryLockRWLockForReading
|
|
|
590 * \sa SDL_UnlockRWLock
|
|
|
591 */
|
|
|
592 extern SDL_DECLSPEC bool SDLCALL SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock) SDL_TRY_ACQUIRE(true, rwlock);
|
|
|
593
|
|
|
594 /**
|
|
|
595 * Unlock the read/write lock.
|
|
|
596 *
|
|
|
597 * Use this function to unlock the rwlock, whether it was locked for read-only
|
|
|
598 * or write operations.
|
|
|
599 *
|
|
|
600 * It is legal for the owning thread to lock an already-locked read-only lock.
|
|
|
601 * It must unlock it the same number of times before it is actually made
|
|
|
602 * available for other threads in the system (this is known as a "recursive
|
|
|
603 * rwlock").
|
|
|
604 *
|
|
|
605 * It is illegal to unlock a rwlock that has not been locked by the current
|
|
|
606 * thread, and doing so results in undefined behavior.
|
|
|
607 *
|
|
|
608 * \param rwlock the rwlock to unlock.
|
|
|
609 *
|
|
|
610 * \since This function is available since SDL 3.2.0.
|
|
|
611 *
|
|
|
612 * \sa SDL_LockRWLockForReading
|
|
|
613 * \sa SDL_LockRWLockForWriting
|
|
|
614 * \sa SDL_TryLockRWLockForReading
|
|
|
615 * \sa SDL_TryLockRWLockForWriting
|
|
|
616 */
|
|
|
617 extern SDL_DECLSPEC void SDLCALL SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_RELEASE_GENERIC(rwlock);
|
|
|
618
|
|
|
619 /**
|
|
|
620 * Destroy a read/write lock created with SDL_CreateRWLock().
|
|
|
621 *
|
|
|
622 * This function must be called on any read/write lock that is no longer
|
|
|
623 * needed. Failure to destroy a rwlock will result in a system memory or
|
|
|
624 * resource leak. While it is safe to destroy a rwlock that is _unlocked_, it
|
|
|
625 * is not safe to attempt to destroy a locked rwlock, and may result in
|
|
|
626 * undefined behavior depending on the platform.
|
|
|
627 *
|
|
|
628 * \param rwlock the rwlock to destroy.
|
|
|
629 *
|
|
|
630 * \since This function is available since SDL 3.2.0.
|
|
|
631 *
|
|
|
632 * \sa SDL_CreateRWLock
|
|
|
633 */
|
|
|
634 extern SDL_DECLSPEC void SDLCALL SDL_DestroyRWLock(SDL_RWLock *rwlock);
|
|
|
635
|
|
|
636 /* @} *//* Read/write lock functions */
|
|
|
637
|
|
|
638
|
|
|
639 /**
|
|
|
640 * \name Semaphore functions
|
|
|
641 */
|
|
|
642 /* @{ */
|
|
|
643
|
|
|
644 /**
|
|
|
645 * A means to manage access to a resource, by count, between threads.
|
|
|
646 *
|
|
|
647 * Semaphores (specifically, "counting semaphores"), let X number of threads
|
|
|
648 * request access at the same time, each thread granted access decrementing a
|
|
|
649 * counter. When the counter reaches zero, future requests block until a prior
|
|
|
650 * thread releases their request, incrementing the counter again.
|
|
|
651 *
|
|
|
652 * Wikipedia has a thorough explanation of the concept:
|
|
|
653 *
|
|
|
654 * https://en.wikipedia.org/wiki/Semaphore_(programming)
|
|
|
655 *
|
|
|
656 * \since This struct is available since SDL 3.2.0.
|
|
|
657 */
|
|
|
658 typedef struct SDL_Semaphore SDL_Semaphore;
|
|
|
659
|
|
|
660 /**
|
|
|
661 * Create a semaphore.
|
|
|
662 *
|
|
|
663 * This function creates a new semaphore and initializes it with the value
|
|
|
664 * `initial_value`. Each wait operation on the semaphore will atomically
|
|
|
665 * decrement the semaphore value and potentially block if the semaphore value
|
|
|
666 * is 0. Each post operation will atomically increment the semaphore value and
|
|
|
667 * wake waiting threads and allow them to retry the wait operation.
|
|
|
668 *
|
|
|
669 * \param initial_value the starting value of the semaphore.
|
|
|
670 * \returns a new semaphore or NULL on failure; call SDL_GetError() for more
|
|
|
671 * information.
|
|
|
672 *
|
|
|
673 * \since This function is available since SDL 3.2.0.
|
|
|
674 *
|
|
|
675 * \sa SDL_DestroySemaphore
|
|
|
676 * \sa SDL_SignalSemaphore
|
|
|
677 * \sa SDL_TryWaitSemaphore
|
|
|
678 * \sa SDL_GetSemaphoreValue
|
|
|
679 * \sa SDL_WaitSemaphore
|
|
|
680 * \sa SDL_WaitSemaphoreTimeout
|
|
|
681 */
|
|
|
682 extern SDL_DECLSPEC SDL_Semaphore * SDLCALL SDL_CreateSemaphore(Uint32 initial_value);
|
|
|
683
|
|
|
684 /**
|
|
|
685 * Destroy a semaphore.
|
|
|
686 *
|
|
|
687 * It is not safe to destroy a semaphore if there are threads currently
|
|
|
688 * waiting on it.
|
|
|
689 *
|
|
|
690 * \param sem the semaphore to destroy.
|
|
|
691 *
|
|
|
692 * \since This function is available since SDL 3.2.0.
|
|
|
693 *
|
|
|
694 * \sa SDL_CreateSemaphore
|
|
|
695 */
|
|
|
696 extern SDL_DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_Semaphore *sem);
|
|
|
697
|
|
|
698 /**
|
|
|
699 * Wait until a semaphore has a positive value and then decrements it.
|
|
|
700 *
|
|
|
701 * This function suspends the calling thread until the semaphore pointed to by
|
|
|
702 * `sem` has a positive value, and then atomically decrement the semaphore
|
|
|
703 * value.
|
|
|
704 *
|
|
|
705 * This function is the equivalent of calling SDL_WaitSemaphoreTimeout() with
|
|
|
706 * a time length of -1.
|
|
|
707 *
|
|
|
708 * \param sem the semaphore wait on.
|
|
|
709 *
|
|
|
710 * \since This function is available since SDL 3.2.0.
|
|
|
711 *
|
|
|
712 * \sa SDL_SignalSemaphore
|
|
|
713 * \sa SDL_TryWaitSemaphore
|
|
|
714 * \sa SDL_WaitSemaphoreTimeout
|
|
|
715 */
|
|
|
716 extern SDL_DECLSPEC void SDLCALL SDL_WaitSemaphore(SDL_Semaphore *sem);
|
|
|
717
|
|
|
718 /**
|
|
|
719 * See if a semaphore has a positive value and decrement it if it does.
|
|
|
720 *
|
|
|
721 * This function checks to see if the semaphore pointed to by `sem` has a
|
|
|
722 * positive value and atomically decrements the semaphore value if it does. If
|
|
|
723 * the semaphore doesn't have a positive value, the function immediately
|
|
|
724 * returns false.
|
|
|
725 *
|
|
|
726 * \param sem the semaphore to wait on.
|
|
|
727 * \returns true if the wait succeeds, false if the wait would block.
|
|
|
728 *
|
|
|
729 * \since This function is available since SDL 3.2.0.
|
|
|
730 *
|
|
|
731 * \sa SDL_SignalSemaphore
|
|
|
732 * \sa SDL_WaitSemaphore
|
|
|
733 * \sa SDL_WaitSemaphoreTimeout
|
|
|
734 */
|
|
|
735 extern SDL_DECLSPEC bool SDLCALL SDL_TryWaitSemaphore(SDL_Semaphore *sem);
|
|
|
736
|
|
|
737 /**
|
|
|
738 * Wait until a semaphore has a positive value and then decrements it.
|
|
|
739 *
|
|
|
740 * This function suspends the calling thread until either the semaphore
|
|
|
741 * pointed to by `sem` has a positive value or the specified time has elapsed.
|
|
|
742 * If the call is successful it will atomically decrement the semaphore value.
|
|
|
743 *
|
|
|
744 * \param sem the semaphore to wait on.
|
|
|
745 * \param timeoutMS the length of the timeout, in milliseconds, or -1 to wait
|
|
|
746 * indefinitely.
|
|
|
747 * \returns true if the wait succeeds or false if the wait times out.
|
|
|
748 *
|
|
|
749 * \since This function is available since SDL 3.2.0.
|
|
|
750 *
|
|
|
751 * \sa SDL_SignalSemaphore
|
|
|
752 * \sa SDL_TryWaitSemaphore
|
|
|
753 * \sa SDL_WaitSemaphore
|
|
|
754 */
|
|
|
755 extern SDL_DECLSPEC bool SDLCALL SDL_WaitSemaphoreTimeout(SDL_Semaphore *sem, Sint32 timeoutMS);
|
|
|
756
|
|
|
757 /**
|
|
|
758 * Atomically increment a semaphore's value and wake waiting threads.
|
|
|
759 *
|
|
|
760 * \param sem the semaphore to increment.
|
|
|
761 *
|
|
|
762 * \since This function is available since SDL 3.2.0.
|
|
|
763 *
|
|
|
764 * \sa SDL_TryWaitSemaphore
|
|
|
765 * \sa SDL_WaitSemaphore
|
|
|
766 * \sa SDL_WaitSemaphoreTimeout
|
|
|
767 */
|
|
|
768 extern SDL_DECLSPEC void SDLCALL SDL_SignalSemaphore(SDL_Semaphore *sem);
|
|
|
769
|
|
|
770 /**
|
|
|
771 * Get the current value of a semaphore.
|
|
|
772 *
|
|
|
773 * \param sem the semaphore to query.
|
|
|
774 * \returns the current value of the semaphore.
|
|
|
775 *
|
|
|
776 * \since This function is available since SDL 3.2.0.
|
|
|
777 */
|
|
|
778 extern SDL_DECLSPEC Uint32 SDLCALL SDL_GetSemaphoreValue(SDL_Semaphore *sem);
|
|
|
779
|
|
|
780 /* @} *//* Semaphore functions */
|
|
|
781
|
|
|
782
|
|
|
783 /**
|
|
|
784 * \name Condition variable functions
|
|
|
785 */
|
|
|
786 /* @{ */
|
|
|
787
|
|
|
788 /**
|
|
|
789 * A means to block multiple threads until a condition is satisfied.
|
|
|
790 *
|
|
|
791 * Condition variables, paired with an SDL_Mutex, let an app halt multiple
|
|
|
792 * threads until a condition has occurred, at which time the app can release
|
|
|
793 * one or all waiting threads.
|
|
|
794 *
|
|
|
795 * Wikipedia has a thorough explanation of the concept:
|
|
|
796 *
|
|
|
797 * https://en.wikipedia.org/wiki/Condition_variable
|
|
|
798 *
|
|
|
799 * \since This struct is available since SDL 3.2.0.
|
|
|
800 */
|
|
|
801 typedef struct SDL_Condition SDL_Condition;
|
|
|
802
|
|
|
803 /**
|
|
|
804 * Create a condition variable.
|
|
|
805 *
|
|
|
806 * \returns a new condition variable or NULL on failure; call SDL_GetError()
|
|
|
807 * for more information.
|
|
|
808 *
|
|
|
809 * \since This function is available since SDL 3.2.0.
|
|
|
810 *
|
|
|
811 * \sa SDL_BroadcastCondition
|
|
|
812 * \sa SDL_SignalCondition
|
|
|
813 * \sa SDL_WaitCondition
|
|
|
814 * \sa SDL_WaitConditionTimeout
|
|
|
815 * \sa SDL_DestroyCondition
|
|
|
816 */
|
|
|
817 extern SDL_DECLSPEC SDL_Condition * SDLCALL SDL_CreateCondition(void);
|
|
|
818
|
|
|
819 /**
|
|
|
820 * Destroy a condition variable.
|
|
|
821 *
|
|
|
822 * \param cond the condition variable to destroy.
|
|
|
823 *
|
|
|
824 * \since This function is available since SDL 3.2.0.
|
|
|
825 *
|
|
|
826 * \sa SDL_CreateCondition
|
|
|
827 */
|
|
|
828 extern SDL_DECLSPEC void SDLCALL SDL_DestroyCondition(SDL_Condition *cond);
|
|
|
829
|
|
|
830 /**
|
|
|
831 * Restart one of the threads that are waiting on the condition variable.
|
|
|
832 *
|
|
|
833 * \param cond the condition variable to signal.
|
|
|
834 *
|
|
|
835 * \threadsafety It is safe to call this function from any thread.
|
|
|
836 *
|
|
|
837 * \since This function is available since SDL 3.2.0.
|
|
|
838 *
|
|
|
839 * \sa SDL_BroadcastCondition
|
|
|
840 * \sa SDL_WaitCondition
|
|
|
841 * \sa SDL_WaitConditionTimeout
|
|
|
842 */
|
|
|
843 extern SDL_DECLSPEC void SDLCALL SDL_SignalCondition(SDL_Condition *cond);
|
|
|
844
|
|
|
845 /**
|
|
|
846 * Restart all threads that are waiting on the condition variable.
|
|
|
847 *
|
|
|
848 * \param cond the condition variable to signal.
|
|
|
849 *
|
|
|
850 * \threadsafety It is safe to call this function from any thread.
|
|
|
851 *
|
|
|
852 * \since This function is available since SDL 3.2.0.
|
|
|
853 *
|
|
|
854 * \sa SDL_SignalCondition
|
|
|
855 * \sa SDL_WaitCondition
|
|
|
856 * \sa SDL_WaitConditionTimeout
|
|
|
857 */
|
|
|
858 extern SDL_DECLSPEC void SDLCALL SDL_BroadcastCondition(SDL_Condition *cond);
|
|
|
859
|
|
|
860 /**
|
|
|
861 * Wait until a condition variable is signaled.
|
|
|
862 *
|
|
|
863 * This function unlocks the specified `mutex` and waits for another thread to
|
|
|
864 * call SDL_SignalCondition() or SDL_BroadcastCondition() on the condition
|
|
|
865 * variable `cond`. Once the condition variable is signaled, the mutex is
|
|
|
866 * re-locked and the function returns.
|
|
|
867 *
|
|
|
868 * The mutex must be locked before calling this function. Locking the mutex
|
|
|
869 * recursively (more than once) is not supported and leads to undefined
|
|
|
870 * behavior.
|
|
|
871 *
|
|
|
872 * This function is the equivalent of calling SDL_WaitConditionTimeout() with
|
|
|
873 * a time length of -1.
|
|
|
874 *
|
|
|
875 * \param cond the condition variable to wait on.
|
|
|
876 * \param mutex the mutex used to coordinate thread access.
|
|
|
877 *
|
|
|
878 * \threadsafety It is safe to call this function from any thread.
|
|
|
879 *
|
|
|
880 * \since This function is available since SDL 3.2.0.
|
|
|
881 *
|
|
|
882 * \sa SDL_BroadcastCondition
|
|
|
883 * \sa SDL_SignalCondition
|
|
|
884 * \sa SDL_WaitConditionTimeout
|
|
|
885 */
|
|
|
886 extern SDL_DECLSPEC void SDLCALL SDL_WaitCondition(SDL_Condition *cond, SDL_Mutex *mutex);
|
|
|
887
|
|
|
888 /**
|
|
|
889 * Wait until a condition variable is signaled or a certain time has passed.
|
|
|
890 *
|
|
|
891 * This function unlocks the specified `mutex` and waits for another thread to
|
|
|
892 * call SDL_SignalCondition() or SDL_BroadcastCondition() on the condition
|
|
|
893 * variable `cond`, or for the specified time to elapse. Once the condition
|
|
|
894 * variable is signaled or the time elapsed, the mutex is re-locked and the
|
|
|
895 * function returns.
|
|
|
896 *
|
|
|
897 * The mutex must be locked before calling this function. Locking the mutex
|
|
|
898 * recursively (more than once) is not supported and leads to undefined
|
|
|
899 * behavior.
|
|
|
900 *
|
|
|
901 * \param cond the condition variable to wait on.
|
|
|
902 * \param mutex the mutex used to coordinate thread access.
|
|
|
903 * \param timeoutMS the maximum time to wait, in milliseconds, or -1 to wait
|
|
|
904 * indefinitely.
|
|
|
905 * \returns true if the condition variable is signaled, false if the condition
|
|
|
906 * is not signaled in the allotted time.
|
|
|
907 *
|
|
|
908 * \threadsafety It is safe to call this function from any thread.
|
|
|
909 *
|
|
|
910 * \since This function is available since SDL 3.2.0.
|
|
|
911 *
|
|
|
912 * \sa SDL_BroadcastCondition
|
|
|
913 * \sa SDL_SignalCondition
|
|
|
914 * \sa SDL_WaitCondition
|
|
|
915 */
|
|
|
916 extern SDL_DECLSPEC bool SDLCALL SDL_WaitConditionTimeout(SDL_Condition *cond,
|
|
|
917 SDL_Mutex *mutex, Sint32 timeoutMS);
|
|
|
918
|
|
|
919 /* @} *//* Condition variable functions */
|
|
|
920
|
|
|
921 /**
|
|
|
922 * \name Thread-safe initialization state functions
|
|
|
923 */
|
|
|
924 /* @{ */
|
|
|
925
|
|
|
926 /**
|
|
|
927 * The current status of an SDL_InitState structure.
|
|
|
928 *
|
|
|
929 * \since This enum is available since SDL 3.2.0.
|
|
|
930 */
|
|
|
931 typedef enum SDL_InitStatus
|
|
|
932 {
|
|
|
933 SDL_INIT_STATUS_UNINITIALIZED,
|
|
|
934 SDL_INIT_STATUS_INITIALIZING,
|
|
|
935 SDL_INIT_STATUS_INITIALIZED,
|
|
|
936 SDL_INIT_STATUS_UNINITIALIZING
|
|
|
937 } SDL_InitStatus;
|
|
|
938
|
|
|
939 /**
|
|
|
940 * A structure used for thread-safe initialization and shutdown.
|
|
|
941 *
|
|
|
942 * Here is an example of using this:
|
|
|
943 *
|
|
|
944 * ```c
|
|
|
945 * static SDL_InitState init;
|
|
|
946 *
|
|
|
947 * bool InitSystem(void)
|
|
|
948 * {
|
|
|
949 * if (!SDL_ShouldInit(&init)) {
|
|
|
950 * // The system is initialized
|
|
|
951 * return true;
|
|
|
952 * }
|
|
|
953 *
|
|
|
954 * // At this point, you should not leave this function without calling SDL_SetInitialized()
|
|
|
955 *
|
|
|
956 * bool initialized = DoInitTasks();
|
|
|
957 * SDL_SetInitialized(&init, initialized);
|
|
|
958 * return initialized;
|
|
|
959 * }
|
|
|
960 *
|
|
|
961 * bool UseSubsystem(void)
|
|
|
962 * {
|
|
|
963 * if (SDL_ShouldInit(&init)) {
|
|
|
964 * // Error, the subsystem isn't initialized
|
|
|
965 * SDL_SetInitialized(&init, false);
|
|
|
966 * return false;
|
|
|
967 * }
|
|
|
968 *
|
|
|
969 * // Do work using the initialized subsystem
|
|
|
970 *
|
|
|
971 * return true;
|
|
|
972 * }
|
|
|
973 *
|
|
|
974 * void QuitSystem(void)
|
|
|
975 * {
|
|
|
976 * if (!SDL_ShouldQuit(&init)) {
|
|
|
977 * // The system is not initialized
|
|
|
978 * return;
|
|
|
979 * }
|
|
|
980 *
|
|
|
981 * // At this point, you should not leave this function without calling SDL_SetInitialized()
|
|
|
982 *
|
|
|
983 * DoQuitTasks();
|
|
|
984 * SDL_SetInitialized(&init, false);
|
|
|
985 * }
|
|
|
986 * ```
|
|
|
987 *
|
|
|
988 * Note that this doesn't protect any resources created during initialization,
|
|
|
989 * or guarantee that nobody is using those resources during cleanup. You
|
|
|
990 * should use other mechanisms to protect those, if that's a concern for your
|
|
|
991 * code.
|
|
|
992 *
|
|
|
993 * \since This struct is available since SDL 3.2.0.
|
|
|
994 */
|
|
|
995 typedef struct SDL_InitState
|
|
|
996 {
|
|
|
997 SDL_AtomicInt status;
|
|
|
998 SDL_ThreadID thread;
|
|
|
999 void *reserved;
|
|
|
1000 } SDL_InitState;
|
|
|
1001
|
|
|
1002 /**
|
|
|
1003 * Return whether initialization should be done.
|
|
|
1004 *
|
|
|
1005 * This function checks the passed in state and if initialization should be
|
|
|
1006 * done, sets the status to `SDL_INIT_STATUS_INITIALIZING` and returns true.
|
|
|
1007 * If another thread is already modifying this state, it will wait until
|
|
|
1008 * that's done before returning.
|
|
|
1009 *
|
|
|
1010 * If this function returns true, the calling code must call
|
|
|
1011 * SDL_SetInitialized() to complete the initialization.
|
|
|
1012 *
|
|
|
1013 * \param state the initialization state to check.
|
|
|
1014 * \returns true if initialization needs to be done, false otherwise.
|
|
|
1015 *
|
|
|
1016 * \threadsafety It is safe to call this function from any thread.
|
|
|
1017 *
|
|
|
1018 * \since This function is available since SDL 3.2.0.
|
|
|
1019 *
|
|
|
1020 * \sa SDL_SetInitialized
|
|
|
1021 * \sa SDL_ShouldQuit
|
|
|
1022 */
|
|
|
1023 extern SDL_DECLSPEC bool SDLCALL SDL_ShouldInit(SDL_InitState *state);
|
|
|
1024
|
|
|
1025 /**
|
|
|
1026 * Return whether cleanup should be done.
|
|
|
1027 *
|
|
|
1028 * This function checks the passed in state and if cleanup should be done,
|
|
|
1029 * sets the status to `SDL_INIT_STATUS_UNINITIALIZING` and returns true.
|
|
|
1030 *
|
|
|
1031 * If this function returns true, the calling code must call
|
|
|
1032 * SDL_SetInitialized() to complete the cleanup.
|
|
|
1033 *
|
|
|
1034 * \param state the initialization state to check.
|
|
|
1035 * \returns true if cleanup needs to be done, false otherwise.
|
|
|
1036 *
|
|
|
1037 * \threadsafety It is safe to call this function from any thread.
|
|
|
1038 *
|
|
|
1039 * \since This function is available since SDL 3.2.0.
|
|
|
1040 *
|
|
|
1041 * \sa SDL_SetInitialized
|
|
|
1042 * \sa SDL_ShouldInit
|
|
|
1043 */
|
|
|
1044 extern SDL_DECLSPEC bool SDLCALL SDL_ShouldQuit(SDL_InitState *state);
|
|
|
1045
|
|
|
1046 /**
|
|
|
1047 * Finish an initialization state transition.
|
|
|
1048 *
|
|
|
1049 * This function sets the status of the passed in state to
|
|
|
1050 * `SDL_INIT_STATUS_INITIALIZED` or `SDL_INIT_STATUS_UNINITIALIZED` and allows
|
|
|
1051 * any threads waiting for the status to proceed.
|
|
|
1052 *
|
|
|
1053 * \param state the initialization state to check.
|
|
|
1054 * \param initialized the new initialization state.
|
|
|
1055 *
|
|
|
1056 * \threadsafety It is safe to call this function from any thread.
|
|
|
1057 *
|
|
|
1058 * \since This function is available since SDL 3.2.0.
|
|
|
1059 *
|
|
|
1060 * \sa SDL_ShouldInit
|
|
|
1061 * \sa SDL_ShouldQuit
|
|
|
1062 */
|
|
|
1063 extern SDL_DECLSPEC void SDLCALL SDL_SetInitialized(SDL_InitState *state, bool initialized);
|
|
|
1064
|
|
|
1065 /* @} *//* Thread-safe initialization state functions */
|
|
|
1066
|
|
|
1067 /* Ends C function definitions when using C++ */
|
|
|
1068 #ifdef __cplusplus
|
|
|
1069 }
|
|
|
1070 #endif
|
|
|
1071 #include <SDL3/SDL_close_code.h>
|
|
|
1072
|
|
|
1073 #endif /* SDL_mutex_h_ */
|