Skip to main content

sdl3_sys/generated/
mutex.rs

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