Skip to main content

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