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