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