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