sdl3_sys/generated/atomic.rs
1//! Atomic operations.
2//!
3//! IMPORTANT: If you are not an expert in concurrent lockless programming, you
4//! should not be using any functions in this file. You should be protecting
5//! your data structures with full mutexes instead.
6//!
7//! ***Seriously, here be dragons!***
8//!
9//! You can find out a little more about lockless programming and the subtle
10//! issues that can arise here:
11//! <https://learn.microsoft.com/en-us/windows/win32/dxtecharts/lockless-programming>
12//!
13//! There's also lots of good information here:
14//!
15//! - <https://www.1024cores.net/home/lock-free-algorithms>
16//! - <https://preshing.com/>
17//!
18//! These operations may or may not actually be implemented using processor
19//! specific atomic operations. When possible they are implemented as true
20//! processor specific atomic operations. When that is not possible the are
21//! implemented using locks that *do* use the available atomic operations.
22//!
23//! All of the atomic operations that modify memory are full memory barriers.
24
25use super::stdinc::*;
26
27/// An atomic spinlock.
28///
29/// The atomic locks are efficient spinlocks using CPU instructions, but are
30/// vulnerable to starvation and can spin forever if a thread holding a lock
31/// has been terminated. For this reason you should minimize the code executed
32/// inside an atomic lock and never do expensive things like API or system
33/// calls while holding them.
34///
35/// They are also vulnerable to starvation if the thread holding the lock is
36/// lower priority than other threads and doesn't get scheduled. In general you
37/// should use mutexes instead, since they have better performance and
38/// contention behavior.
39///
40/// The atomic locks are not safe to lock recursively.
41///
42/// Porting Note: The spin lock functions and type are required and can not be
43/// emulated because they are used in the atomic emulation code.
44#[repr(transparent)]
45#[derive(Default)]
46#[cfg_attr(feature = "debug-impls", derive(Debug))]
47pub struct SDL_SpinLock(pub ::core::ffi::c_int);
48
49impl SDL_SpinLock {
50 /// Initialize a `SDL_SpinLock` from a raw value.
51 #[inline(always)]
52 pub const fn new(value: ::core::ffi::c_int) -> Self {
53 Self(value)
54 }
55}
56
57#[cfg(feature = "metadata")]
58impl sdl3_sys::metadata::GroupMetadata for SDL_SpinLock {
59 const GROUP_METADATA: &'static sdl3_sys::metadata::Group =
60 &crate::metadata::atomic::METADATA_SDL_SpinLock;
61}
62
63unsafe extern "C" {
64 /// Try to lock a spin lock by setting it to a non-zero value.
65 ///
66 /// ***Please note that spinlocks are dangerous if you don't know what you're
67 /// doing. Please be careful using any sort of spinlock!***
68 ///
69 /// ## Parameters
70 /// - `lock`: a pointer to a lock variable.
71 ///
72 /// ## Return value
73 /// Returns true if the lock succeeded, false if the lock is already held.
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_LockSpinlock`]
83 /// - [`SDL_UnlockSpinlock`]
84 pub fn SDL_TryLockSpinlock(lock: *mut SDL_SpinLock) -> ::core::primitive::bool;
85}
86
87unsafe extern "C" {
88 /// Lock a spin lock by setting it to a non-zero value.
89 ///
90 /// ***Please note that spinlocks are dangerous if you don't know what you're
91 /// doing. Please be careful using any sort of spinlock!***
92 ///
93 /// ## Parameters
94 /// - `lock`: a pointer to a lock variable.
95 ///
96 /// ## Thread safety
97 /// It is safe to call this function from any thread.
98 ///
99 /// ## Availability
100 /// This function is available since SDL 3.2.0.
101 ///
102 /// ## See also
103 /// - [`SDL_TryLockSpinlock`]
104 /// - [`SDL_UnlockSpinlock`]
105 pub fn SDL_LockSpinlock(lock: *mut SDL_SpinLock);
106}
107
108unsafe extern "C" {
109 /// Unlock a spin lock by setting it to 0.
110 ///
111 /// Always returns immediately.
112 ///
113 /// ***Please note that spinlocks are dangerous if you don't know what you're
114 /// doing. Please be careful using any sort of spinlock!***
115 ///
116 /// ## Parameters
117 /// - `lock`: a pointer to a lock variable.
118 ///
119 /// ## Thread safety
120 /// It is safe to call this function from any thread.
121 ///
122 /// ## Availability
123 /// This function is available since SDL 3.2.0.
124 ///
125 /// ## See also
126 /// - [`SDL_LockSpinlock`]
127 /// - [`SDL_TryLockSpinlock`]
128 pub fn SDL_UnlockSpinlock(lock: *mut SDL_SpinLock);
129}
130
131apply_cfg!(#[cfg(doc)] => {
132 /// Mark a compiler barrier.
133 ///
134 /// A compiler barrier prevents the compiler from reordering reads and writes
135 /// to globally visible variables across the call.
136 ///
137 /// This macro only prevents the compiler from reordering reads and writes, it
138 /// does not prevent the CPU from reordering reads and writes. However, all of
139 /// the atomic operations that modify memory are full memory barriers.
140 ///
141 /// ## Thread safety
142 /// Obviously this macro is safe to use from any thread at any
143 /// time, but if you find yourself needing this, you are probably
144 /// dealing with some very sensitive code; be careful!
145 ///
146 /// ## Availability
147 /// This macro is available since SDL 3.2.0.
148 #[inline(always)]
149 pub fn SDL_CompilerBarrier() {
150 ::core::sync::atomic::compiler_fence(::core::sync::atomic::Ordering::SeqCst)
151 }
152});
153
154apply_cfg!(#[cfg(not(doc))] => {
155 apply_cfg!(#[cfg(all(not(any(/* always disabled: __clang__ */)), all(windows, target_env = "msvc")))] => {
156 // pragma `intrinsic(_ReadWriteBarrier)`
157 #[inline(always)]
158 pub fn SDL_CompilerBarrier() {
159 ::core::sync::atomic::compiler_fence(::core::sync::atomic::Ordering::SeqCst)
160 }
161 });
162
163 apply_cfg!(#[cfg(not(all(not(any(/* always disabled: __clang__ */)), all(windows, target_env = "msvc"))))] => {
164 apply_cfg!(#[cfg(not(any(doc, target_os = "emscripten")))] => {
165 #[inline(always)]
166 pub fn SDL_CompilerBarrier() {
167 ::core::sync::atomic::compiler_fence(::core::sync::atomic::Ordering::SeqCst)
168 }
169 });
170
171 apply_cfg!(#[cfg(any(doc, target_os = "emscripten"))] => {
172 #[inline(always)]
173 pub fn SDL_CompilerBarrier() {
174 ::core::sync::atomic::compiler_fence(::core::sync::atomic::Ordering::SeqCst)
175 }
176 });
177
178 });
179
180});
181
182#[inline(always)]
183pub fn SDL_MemoryBarrierRelease() {
184 ::core::sync::atomic::fence(::core::sync::atomic::Ordering::Release)
185}
186
187unsafe extern "C" {
188 /// Insert a memory release barrier (function version).
189 ///
190 /// Please refer to [`SDL_MemoryBarrierRelease`] for details. This is a function
191 /// version, which might be useful if you need to use this functionality from a
192 /// scripting language, etc. Also, some of the macro versions call this
193 /// function behind the scenes, where more heavy lifting can happen inside of
194 /// SDL. Generally, though, an app written in C/C++/etc should use the macro
195 /// version, as it will be more efficient.
196 ///
197 /// ## Thread safety
198 /// Obviously this function is safe to use from any thread at any
199 /// time, but if you find yourself needing this, you are probably
200 /// dealing with some very sensitive code; be careful!
201 ///
202 /// ## Availability
203 /// This function is available since SDL 3.2.0.
204 ///
205 /// ## See also
206 /// - [`SDL_MemoryBarrierRelease`]
207 pub fn SDL_MemoryBarrierReleaseFunction();
208}
209
210#[inline(always)]
211pub fn SDL_MemoryBarrierAcquire() {
212 ::core::sync::atomic::fence(::core::sync::atomic::Ordering::Acquire)
213}
214
215unsafe extern "C" {
216 /// Insert a memory acquire barrier (function version).
217 ///
218 /// Please refer to [`SDL_MemoryBarrierRelease`] for details. This is a function
219 /// version, which might be useful if you need to use this functionality from a
220 /// scripting language, etc. Also, some of the macro versions call this
221 /// function behind the scenes, where more heavy lifting can happen inside of
222 /// SDL. Generally, though, an app written in C/C++/etc should use the macro
223 /// version, as it will be more efficient.
224 ///
225 /// ## Thread safety
226 /// Obviously this function is safe to use from any thread at any
227 /// time, but if you find yourself needing this, you are probably
228 /// dealing with some very sensitive code; be careful!
229 ///
230 /// ## Availability
231 /// This function is available since SDL 3.2.0.
232 ///
233 /// ## See also
234 /// - [`SDL_MemoryBarrierAcquire`]
235 pub fn SDL_MemoryBarrierAcquireFunction();
236}
237
238apply_cfg!(#[cfg(doc)] => {
239});
240
241apply_cfg!(#[cfg(not(doc))] => {
242 apply_cfg!(#[cfg(all(any(any(target_arch = "powerpc", target_arch = "powerpc64"), any(target_arch = "powerpc", target_arch = "powerpc64")), any(/* always disabled: __GNUC__ */)))] => {
243 });
244
245 apply_cfg!(#[cfg(not(all(any(any(target_arch = "powerpc", target_arch = "powerpc64"), any(target_arch = "powerpc", target_arch = "powerpc64")), any(/* always disabled: __GNUC__ */))))] => {
246 });
247
248});
249
250apply_cfg!(#[cfg(doc)] => {
251 /// A macro to insert a CPU-specific "pause" instruction into the program.
252 ///
253 /// This can be useful in busy-wait loops, as it serves as a hint to the CPU as
254 /// to the program's intent; some CPUs can use this to do more efficient
255 /// processing. On some platforms, this doesn't do anything, so using this
256 /// macro might just be a harmless no-op.
257 ///
258 /// Note that if you are busy-waiting, there are often more-efficient
259 /// approaches with other synchronization primitives: mutexes, semaphores,
260 /// condition variables, etc.
261 ///
262 /// ## Thread safety
263 /// This macro is safe to use from any thread.
264 ///
265 /// ## Availability
266 /// This macro is available since SDL 3.2.0.
267 #[inline(always)]
268 pub fn SDL_CPUPauseInstruction() {
269 ::core::hint::spin_loop();
270 }
271});
272
273apply_cfg!(#[cfg(not(doc))] => {
274 apply_cfg!(#[cfg(all(any(any(/* always disabled: __GNUC__ */), any(/* always disabled: __clang__ */)), any(target_arch = "x86", target_arch = "x86_64")))] => {
275 #[inline(always)]
276 pub fn SDL_CPUPauseInstruction() {
277 ::core::hint::spin_loop();
278 }
279 });
280
281 apply_cfg!(#[cfg(not(all(any(any(/* always disabled: __GNUC__ */), any(/* always disabled: __clang__ */)), any(target_arch = "x86", target_arch = "x86_64"))))] => {
282 #[inline(always)]
283 pub fn SDL_CPUPauseInstruction() {
284 ::core::hint::spin_loop();
285 }
286 });
287
288});
289
290/// A type representing an atomic integer value.
291///
292/// This can be used to manage a value that is synchronized across multiple
293/// CPUs without a race condition; when an app sets a value with
294/// [`SDL_SetAtomicInt`] all other threads, regardless of the CPU it is running on,
295/// will see that value when retrieved with [`SDL_GetAtomicInt`], regardless of CPU
296/// caches, etc.
297///
298/// This is also useful for atomic compare-and-swap operations: a thread can
299/// change the value as long as its current value matches expectations. When
300/// done in a loop, one can guarantee data consistency across threads without a
301/// lock (but the usual warnings apply: if you don't know what you're doing, or
302/// you don't do it carefully, you can confidently cause any number of
303/// disasters with this, so in most cases, you _should_ use a mutex instead of
304/// this!).
305///
306/// This is a struct so people don't accidentally use numeric operations on it
307/// directly. You have to use SDL atomic functions.
308///
309/// ## Availability
310/// This struct is available since SDL 3.2.0.
311///
312/// ## See also
313/// - [`SDL_CompareAndSwapAtomicInt`]
314/// - [`SDL_GetAtomicInt`]
315/// - [`SDL_SetAtomicInt`]
316/// - [`SDL_AddAtomicInt`]
317#[repr(C)]
318#[derive(Default)]
319#[cfg_attr(feature = "debug-impls", derive(Debug))]
320pub struct SDL_AtomicInt {
321 pub value: ::core::ffi::c_int,
322}
323
324unsafe extern "C" {
325 /// Set an atomic variable to a new value if it is currently an old value.
326 ///
327 /// ***Note: If you don't know what this function is for, you shouldn't use
328 /// it!***
329 ///
330 /// ## Parameters
331 /// - `a`: a pointer to an [`SDL_AtomicInt`] variable to be modified.
332 /// - `oldval`: the old value.
333 /// - `newval`: the new value.
334 ///
335 /// ## Return value
336 /// Returns true if the atomic variable was set, false otherwise.
337 ///
338 /// ## Thread safety
339 /// It is safe to call this function from any thread.
340 ///
341 /// ## Availability
342 /// This function is available since SDL 3.2.0.
343 ///
344 /// ## See also
345 /// - [`SDL_GetAtomicInt`]
346 /// - [`SDL_SetAtomicInt`]
347 pub fn SDL_CompareAndSwapAtomicInt(
348 a: *mut SDL_AtomicInt,
349 oldval: ::core::ffi::c_int,
350 newval: ::core::ffi::c_int,
351 ) -> ::core::primitive::bool;
352}
353
354unsafe extern "C" {
355 /// Set an atomic variable to a value.
356 ///
357 /// This function also acts as a full memory barrier.
358 ///
359 /// ***Note: If you don't know what this function is for, you shouldn't use
360 /// it!***
361 ///
362 /// ## Parameters
363 /// - `a`: a pointer to an [`SDL_AtomicInt`] variable to be modified.
364 /// - `v`: the desired value.
365 ///
366 /// ## Return value
367 /// Returns the previous value of the atomic variable.
368 ///
369 /// ## Thread safety
370 /// It is safe to call this function from any thread.
371 ///
372 /// ## Availability
373 /// This function is available since SDL 3.2.0.
374 ///
375 /// ## See also
376 /// - [`SDL_GetAtomicInt`]
377 pub fn SDL_SetAtomicInt(a: *mut SDL_AtomicInt, v: ::core::ffi::c_int) -> ::core::ffi::c_int;
378}
379
380unsafe extern "C" {
381 /// Get the value of an atomic variable.
382 ///
383 /// ***Note: If you don't know what this function is for, you shouldn't use
384 /// it!***
385 ///
386 /// ## Parameters
387 /// - `a`: a pointer to an [`SDL_AtomicInt`] variable.
388 ///
389 /// ## Return value
390 /// Returns the current value of an atomic variable.
391 ///
392 /// ## Thread safety
393 /// It is safe to call this function from any thread.
394 ///
395 /// ## Availability
396 /// This function is available since SDL 3.2.0.
397 ///
398 /// ## See also
399 /// - [`SDL_SetAtomicInt`]
400 pub fn SDL_GetAtomicInt(a: *mut SDL_AtomicInt) -> ::core::ffi::c_int;
401}
402
403unsafe extern "C" {
404 /// Add to an atomic variable.
405 ///
406 /// This function also acts as a full memory barrier.
407 ///
408 /// ***Note: If you don't know what this function is for, you shouldn't use
409 /// it!***
410 ///
411 /// ## Parameters
412 /// - `a`: a pointer to an [`SDL_AtomicInt`] variable to be modified.
413 /// - `v`: the desired value to add.
414 ///
415 /// ## Return value
416 /// Returns the previous value of the atomic variable.
417 ///
418 /// ## Thread safety
419 /// It is safe to call this function from any thread.
420 ///
421 /// ## Availability
422 /// This function is available since SDL 3.2.0.
423 ///
424 /// ## See also
425 /// - [`SDL_AtomicDecRef`]
426 /// - [`SDL_AtomicIncRef`]
427 pub fn SDL_AddAtomicInt(a: *mut SDL_AtomicInt, v: ::core::ffi::c_int) -> ::core::ffi::c_int;
428}
429
430/// Increment an atomic variable used as a reference count.
431///
432/// ***Note: If you don't know what this macro is for, you shouldn't use it!***
433///
434/// ## Parameters
435/// - `a`: a pointer to an [`SDL_AtomicInt`] to increment.
436///
437/// ## Return value
438/// Returns the previous value of the atomic variable.
439///
440/// ## Thread safety
441/// It is safe to call this macro from any thread.
442///
443/// ## Availability
444/// This macro is available since SDL 3.2.0.
445///
446/// ## See also
447/// - [`SDL_AtomicDecRef`]
448#[inline(always)]
449pub unsafe fn SDL_AtomicIncRef(a: *mut SDL_AtomicInt) -> ::core::ffi::c_int {
450 unsafe { SDL_AddAtomicInt(a, 1) }
451}
452
453/// Decrement an atomic variable used as a reference count.
454///
455/// ***Note: If you don't know what this macro is for, you shouldn't use it!***
456///
457/// ## Parameters
458/// - `a`: a pointer to an [`SDL_AtomicInt`] to decrement.
459///
460/// ## Return value
461/// Returns true if the variable reached zero after decrementing, false
462/// otherwise.
463///
464/// ## Thread safety
465/// It is safe to call this macro from any thread.
466///
467/// ## Availability
468/// This macro is available since SDL 3.2.0.
469///
470/// ## See also
471/// - [`SDL_AtomicIncRef`]
472#[inline(always)]
473pub unsafe fn SDL_AtomicDecRef(a: *mut SDL_AtomicInt) -> ::core::primitive::bool {
474 (unsafe { SDL_AddAtomicInt(a, -1_i32) } == 1_i32)
475}
476
477/// A type representing an atomic unsigned 32-bit value.
478///
479/// This can be used to manage a value that is synchronized across multiple
480/// CPUs without a race condition; when an app sets a value with
481/// [`SDL_SetAtomicU32`] all other threads, regardless of the CPU it is running on,
482/// will see that value when retrieved with [`SDL_GetAtomicU32`], regardless of CPU
483/// caches, etc.
484///
485/// This is also useful for atomic compare-and-swap operations: a thread can
486/// change the value as long as its current value matches expectations. When
487/// done in a loop, one can guarantee data consistency across threads without a
488/// lock (but the usual warnings apply: if you don't know what you're doing, or
489/// you don't do it carefully, you can confidently cause any number of
490/// disasters with this, so in most cases, you _should_ use a mutex instead of
491/// this!).
492///
493/// This is a struct so people don't accidentally use numeric operations on it
494/// directly. You have to use SDL atomic functions.
495///
496/// ## Availability
497/// This struct is available since SDL 3.2.0.
498///
499/// ## See also
500/// - [`SDL_CompareAndSwapAtomicU32`]
501/// - [`SDL_GetAtomicU32`]
502/// - [`SDL_SetAtomicU32`]
503#[repr(C)]
504#[derive(Default)]
505#[cfg_attr(feature = "debug-impls", derive(Debug))]
506pub struct SDL_AtomicU32 {
507 pub value: Uint32,
508}
509
510unsafe extern "C" {
511 /// Set an atomic variable to a new value if it is currently an old value.
512 ///
513 /// ***Note: If you don't know what this function is for, you shouldn't use
514 /// it!***
515 ///
516 /// ## Parameters
517 /// - `a`: a pointer to an [`SDL_AtomicU32`] variable to be modified.
518 /// - `oldval`: the old value.
519 /// - `newval`: the new value.
520 ///
521 /// ## Return value
522 /// Returns true if the atomic variable was set, false otherwise.
523 ///
524 /// ## Thread safety
525 /// It is safe to call this function from any thread.
526 ///
527 /// ## Availability
528 /// This function is available since SDL 3.2.0.
529 ///
530 /// ## See also
531 /// - [`SDL_GetAtomicU32`]
532 /// - [`SDL_SetAtomicU32`]
533 pub fn SDL_CompareAndSwapAtomicU32(
534 a: *mut SDL_AtomicU32,
535 oldval: Uint32,
536 newval: Uint32,
537 ) -> ::core::primitive::bool;
538}
539
540unsafe extern "C" {
541 /// Set an atomic variable to a value.
542 ///
543 /// This function also acts as a full memory barrier.
544 ///
545 /// ***Note: If you don't know what this function is for, you shouldn't use
546 /// it!***
547 ///
548 /// ## Parameters
549 /// - `a`: a pointer to an [`SDL_AtomicU32`] variable to be modified.
550 /// - `v`: the desired value.
551 ///
552 /// ## Return value
553 /// Returns the previous value of the atomic variable.
554 ///
555 /// ## Thread safety
556 /// It is safe to call this function from any thread.
557 ///
558 /// ## Availability
559 /// This function is available since SDL 3.2.0.
560 ///
561 /// ## See also
562 /// - [`SDL_GetAtomicU32`]
563 pub fn SDL_SetAtomicU32(a: *mut SDL_AtomicU32, v: Uint32) -> Uint32;
564}
565
566unsafe extern "C" {
567 /// Get the value of an atomic variable.
568 ///
569 /// ***Note: If you don't know what this function is for, you shouldn't use
570 /// it!***
571 ///
572 /// ## Parameters
573 /// - `a`: a pointer to an [`SDL_AtomicU32`] variable.
574 ///
575 /// ## Return value
576 /// Returns the current value of an atomic variable.
577 ///
578 /// ## Thread safety
579 /// It is safe to call this function from any thread.
580 ///
581 /// ## Availability
582 /// This function is available since SDL 3.2.0.
583 ///
584 /// ## See also
585 /// - [`SDL_SetAtomicU32`]
586 pub fn SDL_GetAtomicU32(a: *mut SDL_AtomicU32) -> Uint32;
587}
588
589unsafe extern "C" {
590 /// Add to an atomic variable.
591 ///
592 /// This function also acts as a full memory barrier.
593 ///
594 /// ***Note: If you don't know what this function is for, you shouldn't use
595 /// it!***
596 ///
597 /// ## Parameters
598 /// - `a`: a pointer to an [`SDL_AtomicU32`] variable to be modified.
599 /// - `v`: the desired value to add or subtract.
600 ///
601 /// ## Return value
602 /// Returns the previous value of the atomic variable.
603 ///
604 /// ## Thread safety
605 /// It is safe to call this function from any thread.
606 ///
607 /// ## Availability
608 /// This function is available since SDL 3.4.0.
609 pub fn SDL_AddAtomicU32(a: *mut SDL_AtomicU32, v: ::core::ffi::c_int) -> Uint32;
610}
611
612unsafe extern "C" {
613 /// Set a pointer to a new value if it is currently an old value.
614 ///
615 /// ***Note: If you don't know what this function is for, you shouldn't use
616 /// it!***
617 ///
618 /// ## Parameters
619 /// - `a`: a pointer to a pointer.
620 /// - `oldval`: the old pointer value.
621 /// - `newval`: the new pointer value.
622 ///
623 /// ## Return value
624 /// Returns true if the pointer was set, false otherwise.
625 ///
626 /// ## Thread safety
627 /// It is safe to call this function from any thread.
628 ///
629 /// ## Availability
630 /// This function is available since SDL 3.2.0.
631 ///
632 /// ## See also
633 /// - [`SDL_CompareAndSwapAtomicInt`]
634 /// - [`SDL_GetAtomicPointer`]
635 /// - [`SDL_SetAtomicPointer`]
636 pub fn SDL_CompareAndSwapAtomicPointer(
637 a: *mut *mut ::core::ffi::c_void,
638 oldval: *mut ::core::ffi::c_void,
639 newval: *mut ::core::ffi::c_void,
640 ) -> ::core::primitive::bool;
641}
642
643unsafe extern "C" {
644 /// Set a pointer to a value atomically.
645 ///
646 /// ***Note: If you don't know what this function is for, you shouldn't use
647 /// it!***
648 ///
649 /// ## Parameters
650 /// - `a`: a pointer to a pointer.
651 /// - `v`: the desired pointer value.
652 ///
653 /// ## Return value
654 /// Returns the previous value of the pointer.
655 ///
656 /// ## Thread safety
657 /// It is safe to call this function from any thread.
658 ///
659 /// ## Availability
660 /// This function is available since SDL 3.2.0.
661 ///
662 /// ## See also
663 /// - [`SDL_CompareAndSwapAtomicPointer`]
664 /// - [`SDL_GetAtomicPointer`]
665 pub fn SDL_SetAtomicPointer(
666 a: *mut *mut ::core::ffi::c_void,
667 v: *mut ::core::ffi::c_void,
668 ) -> *mut ::core::ffi::c_void;
669}
670
671unsafe extern "C" {
672 /// Get the value of a pointer atomically.
673 ///
674 /// ***Note: If you don't know what this function is for, you shouldn't use
675 /// it!***
676 ///
677 /// ## Parameters
678 /// - `a`: a pointer to a pointer.
679 ///
680 /// ## Return value
681 /// Returns the current value of a pointer.
682 ///
683 /// ## Thread safety
684 /// It is safe to call this function from any thread.
685 ///
686 /// ## Availability
687 /// This function is available since SDL 3.2.0.
688 ///
689 /// ## See also
690 /// - [`SDL_CompareAndSwapAtomicPointer`]
691 /// - [`SDL_SetAtomicPointer`]
692 pub fn SDL_GetAtomicPointer(a: *mut *mut ::core::ffi::c_void) -> *mut ::core::ffi::c_void;
693}
694
695#[cfg(doc)]
696use crate::everything::*;