|
SDL3pp
A slim C++ wrapper for SDL3
|
Atomic operations. More...
Classes | |
| struct | SDL::AtomicInt |
| A type representing an atomic integer value. More... | |
| struct | SDL::AtomicU32 |
| A type representing an atomic unsigned 32-bit value. More... | |
| class | SDL::AtomicPointer< T > |
| A type representing an atomic of an arbitrary pointer. More... | |
Typedefs | |
| using | SDL::AtomicIntRaw = SDL_AtomicInt |
| Alias to raw representation for AtomicInt. | |
| using | SDL::AtomicU32Raw = SDL_AtomicU32 |
| Alias to raw representation for AtomicU32. | |
Functions | |
| SDL_FORCE_INLINE void | SDL::CompilerBarrier () |
| Mark a compiler barrier. | |
| void | SDL::MemoryBarrierReleaseFunction () |
| Insert a memory release barrier (function version). | |
| void | SDL::MemoryBarrierAcquireFunction () |
| Insert a memory acquire barrier (function version). | |
| SDL_FORCE_INLINE void | SDL::MemoryBarrierRelease () |
| Insert a memory release barrier. | |
| SDL_FORCE_INLINE void | SDL::MemoryBarrierAcquire () |
| Insert a memory acquire barrier. | |
| SDL_FORCE_INLINE void | SDL::CPUPauseInstruction () |
| A function to insert a CPU-specific "pause" instruction into the program. | |
| bool | SDL::CompareAndSwapAtomicInt (AtomicIntRaw *a, int oldval, int newval) |
| Set an atomic variable to a new value if it is currently an old value. | |
| int | SDL::SetAtomicInt (AtomicIntRaw *a, int v) |
| Set an atomic variable to a value. | |
| int | SDL::GetAtomicInt (AtomicIntRaw *a) |
| Get the value of an atomic variable. | |
| int | SDL::AddAtomicInt (AtomicIntRaw *a, int v) |
| Add to an atomic variable. | |
| bool | SDL::AtomicIncRef (AtomicIntRaw *a) |
| Increment an atomic variable used as a reference count. | |
| bool | SDL::AtomicDecRef (AtomicIntRaw *a) |
| Decrement an atomic variable used as a reference count. | |
| bool | SDL::CompareAndSwapAtomicU32 (AtomicU32Raw *a, Uint32 oldval, Uint32 newval) |
| Set an atomic variable to a new value if it is currently an old value. | |
| Uint32 | SDL::SetAtomicU32 (AtomicU32Raw *a, Uint32 v) |
| Set an atomic variable to a value. | |
| Uint32 | SDL::GetAtomicU32 (AtomicU32Raw *a) |
| Get the value of an atomic variable. | |
| Uint32 | SDL::AddAtomicU32 (AtomicU32Raw *a, int v) |
| Add to an atomic variable. | |
| bool | SDL::AtomicInt::CompareAndSwap (int oldval, int newval) |
| Set an atomic variable to a new value if it is currently an old value. | |
| int | SDL::AtomicInt::Set (int v) |
| Set an atomic variable to a value. | |
| int | SDL::AtomicInt::Get () |
| Get the value of an atomic variable. | |
| int | SDL::AtomicInt::Add (int v) |
| Add to an atomic variable. | |
| bool | SDL::AtomicInt::AtomicIncRef () |
| Increment an atomic variable used as a reference count. | |
| bool | SDL::AtomicInt::AtomicDecRef () |
| Decrement an atomic variable used as a reference count. | |
| bool | SDL::AtomicU32::CompareAndSwap (Uint32 oldval, Uint32 newval) |
| Set an atomic variable to a new value if it is currently an old value. | |
| Uint32 | SDL::AtomicU32::Set (Uint32 v) |
| Set an atomic variable to a value. | |
| Uint32 | SDL::AtomicU32::Get () |
| Get the value of an atomic variable. | |
| Uint32 | SDL::AtomicU32::Add (int v) |
| Add to an atomic variable. | |
| bool | SDL::AtomicPointer< T >::CompareAndSwap (T *oldval, T *newval) |
| Set a pointer to a new value if it is currently an old value. | |
| T * | SDL::AtomicPointer< T >::Set (T *v) |
| Set a pointer to a value atomically. | |
| T * | SDL::AtomicPointer< T >::Get () |
| Get the value of a pointer atomically. | |
Atomic operations.
IMPORTANT: If you are not an expert in concurrent lockless programming, you should not be using any functions in this file. You should be protecting your data structures with full mutexes instead.
Seriously, here be dragons!
You can find out a little more about lockless programming and the subtle issues that can arise here: https://learn.microsoft.com/en-us/windows/win32/dxtecharts/lockless-programming
There's also lots of good information here:
These operations may or may not actually be implemented using processor specific atomic operations. When possible they are implemented as true processor specific atomic operations. When that is not possible the are implemented using locks that do use the available atomic operations.
All of the atomic operations that modify memory are full memory barriers.
|
inline |
Add to an atomic variable.
This function also acts as a full memory barrier.
Note: If you don't know what this function is for, you shouldn't use it!
| v | the desired value to add. |
|
inline |
Add to an atomic variable.
This function also acts as a full memory barrier.
Note: If you don't know what this function is for, you shouldn't use it!
| v | the desired value to add or subtract. |
|
inline |
Add to an atomic variable.
This function also acts as a full memory barrier.
Note: If you don't know what this function is for, you shouldn't use it!
| a | a pointer to an AtomicInt variable to be modified. |
| v | the desired value to add. |
|
inline |
Add to an atomic variable.
This function also acts as a full memory barrier.
Note: If you don't know what this function is for, you shouldn't use it!
| a | a pointer to an AtomicU32 variable to be modified. |
| v | the desired value to add or subtract. |
|
inline |
Decrement an atomic variable used as a reference count.
Note: If you don't know what this function is for, you shouldn't use it!
| a | a pointer to an AtomicInt to decrement. |
|
inline |
Decrement an atomic variable used as a reference count.
Note: If you don't know what this function is for, you shouldn't use it!
|
inline |
Increment an atomic variable used as a reference count.
Note: If you don't know what this function is for, you shouldn't use it!
| a | a pointer to an AtomicInt to increment. |
|
inline |
Increment an atomic variable used as a reference count.
Note: If you don't know what this function is for, you shouldn't use it!
|
inline |
Set an atomic variable to a new value if it is currently an old value.
Note: If you don't know what this function is for, you shouldn't use it!
| oldval | the old value. |
| newval | the new value. |
|
inline |
Set a pointer to a new value if it is currently an old value.
Note: If you don't know what this function is for, you shouldn't use it!
| oldval | the old pointer value. |
| newval | the new pointer value. |
Set an atomic variable to a new value if it is currently an old value.
Note: If you don't know what this function is for, you shouldn't use it!
| oldval | the old value. |
| newval | the new value. |
|
inline |
Set an atomic variable to a new value if it is currently an old value.
Note: If you don't know what this function is for, you shouldn't use it!
| a | a pointer to an AtomicInt variable to be modified. |
| oldval | the old value. |
| newval | the new value. |
|
inline |
Set an atomic variable to a new value if it is currently an old value.
Note: If you don't know what this function is for, you shouldn't use it!
| a | a pointer to an AtomicU32 variable to be modified. |
| oldval | the old value. |
| newval | the new value. |
| SDL_FORCE_INLINE void SDL::CompilerBarrier | ( | ) |
Mark a compiler barrier.
A compiler barrier prevents the compiler from reordering reads and writes to globally visible variables across the call.
This function only prevents the compiler from reordering reads and writes, it does not prevent the CPU from reordering reads and writes. However, all of the atomic operations that modify memory are full memory barriers.
| SDL_FORCE_INLINE void SDL::CPUPauseInstruction | ( | ) |
A function to insert a CPU-specific "pause" instruction into the program.
This can be useful in busy-wait loops, as it serves as a hint to the CPU as to the program's intent; some CPUs can use this to do more efficient processing. On some platforms, this doesn't do anything, so using this function might just be a harmless no-op.
Note that if you are busy-waiting, there are often more-efficient approaches with other synchronization primitives: mutexes, semaphores, condition variables, etc.
|
inline |
Get the value of an atomic variable.
Note: If you don't know what this function is for, you shouldn't use it!
|
inline |
Get the value of a pointer atomically.
Note: If you don't know what this function is for, you shouldn't use it!
|
inline |
Get the value of an atomic variable.
Note: If you don't know what this function is for, you shouldn't use it!
|
inline |
Get the value of an atomic variable.
Note: If you don't know what this function is for, you shouldn't use it!
| a | a pointer to an AtomicInt variable. |
|
inline |
Get the value of an atomic variable.
Note: If you don't know what this function is for, you shouldn't use it!
| a | a pointer to an AtomicU32 variable. |
| SDL_FORCE_INLINE void SDL::MemoryBarrierAcquire | ( | ) |
Insert a memory acquire barrier.
Please see MemoryBarrierRelease for the details on what memory barriers are and when to use them.
This is the macro version of this functionality; if possible, SDL will use compiler intrinsics or inline assembly, but some platforms might need to call the function version of this, MemoryBarrierAcquireFunction, to do the heavy lifting. Apps that can use the macro should favor it over the function.
|
inline |
Insert a memory acquire barrier (function version).
Please refer to MemoryBarrierRelease for details. This is a function version, which might be useful if you need to use this functionality from a scripting language, etc. Also, some of the macro versions call this function behind the scenes, where more heavy lifting can happen inside of SDL. Generally, though, an app written in C/C++/etc should use the macro version, as it will be more efficient.
| SDL_FORCE_INLINE void SDL::MemoryBarrierRelease | ( | ) |
Insert a memory release barrier.
Memory barriers are designed to prevent reads and writes from being reordered by the compiler and being seen out of order on multi-core CPUs.
A typical pattern would be for thread A to write some data and a flag, and for thread B to read the flag and get the data. In this case you would insert a release barrier between writing the data and the flag, guaranteeing that the data write completes no later than the flag is written, and you would insert an acquire barrier between reading the flag and reading the data, to ensure that all the reads associated with the flag have completed.
In this pattern you should always see a release barrier paired with an acquire barrier and you should gate the data reads/writes with a single flag variable.
For more information on these semantics, take a look at the blog post: http://preshing.com/20120913/acquire-and-release-semantics
This is the macro version of this functionality; if possible, SDL will use compiler intrinsics or inline assembly, but some platforms might need to call the function version of this, MemoryBarrierReleaseFunction to do the heavy lifting. Apps that can use the macro should favor it over the function.
|
inline |
Insert a memory release barrier (function version).
Please refer to MemoryBarrierRelease for details. This is a function version, which might be useful if you need to use this functionality from a scripting language, etc. Also, some of the macro versions call this function behind the scenes, where more heavy lifting can happen inside of SDL. Generally, though, an app written in C/C++/etc should use the macro version, as it will be more efficient.
|
inline |
Set an atomic variable to a value.
This function also acts as a full memory barrier.
Note: If you don't know what this function is for, you shouldn't use it!
| v | the desired value. |
|
inline |
Set a pointer to a value atomically.
Note: If you don't know what this function is for, you shouldn't use it!
| v | the desired pointer value. |
Set an atomic variable to a value.
This function also acts as a full memory barrier.
Note: If you don't know what this function is for, you shouldn't use it!
| v | the desired value. |
|
inline |
Set an atomic variable to a value.
This function also acts as a full memory barrier.
Note: If you don't know what this function is for, you shouldn't use it!
| a | a pointer to an AtomicInt variable to be modified. |
| v | the desired value. |
|
inline |
Set an atomic variable to a value.
This function also acts as a full memory barrier.
Note: If you don't know what this function is for, you shouldn't use it!
| a | a pointer to an AtomicU32 variable to be modified. |
| v | the desired value. |