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::*;