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