SDL 3.0
SDL_atomic.h File Reference
+ Include dependency graph for SDL_atomic.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  SDL_AtomicInt
 

Macros

#define SDL_CompilerBarrier()   { SDL_SpinLock _tmp = 0; SDL_LockSpinlock(&_tmp); SDL_UnlockSpinlock(&_tmp); }
 
#define SDL_MemoryBarrierRelease()   SDL_CompilerBarrier()
 
#define SDL_MemoryBarrierAcquire()   SDL_CompilerBarrier()
 
#define SDL_CPUPauseInstruction()
 
#define SDL_AtomicIncRef(a)   SDL_AtomicAdd(a, 1)
 
#define SDL_AtomicDecRef(a)   (SDL_AtomicAdd(a, -1) == 1)
 

Typedefs

typedef int SDL_SpinLock
 

Functions

SDL_bool SDL_TryLockSpinlock (SDL_SpinLock *lock)
 
void SDL_LockSpinlock (SDL_SpinLock *lock)
 
void SDL_UnlockSpinlock (SDL_SpinLock *lock)
 
void SDL_MemoryBarrierReleaseFunction (void)
 
void SDL_MemoryBarrierAcquireFunction (void)
 
SDL_bool SDL_AtomicCompareAndSwap (SDL_AtomicInt *a, int oldval, int newval)
 
int SDL_AtomicSet (SDL_AtomicInt *a, int v)
 
int SDL_AtomicGet (SDL_AtomicInt *a)
 
int SDL_AtomicAdd (SDL_AtomicInt *a, int v)
 
SDL_bool SDL_AtomicCompareAndSwapPointer (void **a, void *oldval, void *newval)
 
void * SDL_AtomicSetPtr (void **a, void *v)
 
void * SDL_AtomicGetPtr (void **a)
 

Macro Definition Documentation

◆ SDL_AtomicDecRef

#define SDL_AtomicDecRef (   a)    (SDL_AtomicAdd(a, -1) == 1)

Decrement an atomic variable used as a reference count.

Note: If you don't know what this macro is for, you shouldn't use it!

Parameters
aa pointer to an SDL_AtomicInt to increment.
Returns
SDL_TRUE if the variable reached zero after decrementing, SDL_FALSE otherwise.
Since
This macro is available since SDL 3.0.0.
See also
SDL_AtomicIncRef

Definition at line 439 of file SDL_atomic.h.

◆ SDL_AtomicIncRef

#define SDL_AtomicIncRef (   a)    SDL_AtomicAdd(a, 1)

Increment an atomic variable used as a reference count.

Note: If you don't know what this macro is for, you shouldn't use it!

Parameters
aa pointer to an SDL_AtomicInt to increment.
Returns
the previous value of the atomic variable.
Since
This macro is available since SDL 3.0.0.
See also
SDL_AtomicDecRef

Definition at line 421 of file SDL_atomic.h.

◆ SDL_CompilerBarrier

#define SDL_CompilerBarrier ( )    { SDL_SpinLock _tmp = 0; SDL_LockSpinlock(&_tmp); SDL_UnlockSpinlock(&_tmp); }

Definition at line 164 of file SDL_atomic.h.

165{ SDL_SpinLock _tmp = 0; SDL_LockSpinlock(&_tmp); SDL_UnlockSpinlock(&_tmp); }
int SDL_SpinLock
Definition SDL_atomic.h:82
void SDL_LockSpinlock(SDL_SpinLock *lock)
void SDL_UnlockSpinlock(SDL_SpinLock *lock)

◆ SDL_CPUPauseInstruction

#define SDL_CPUPauseInstruction ( )

Definition at line 298 of file SDL_atomic.h.

◆ SDL_MemoryBarrierAcquire

#define SDL_MemoryBarrierAcquire ( )    SDL_CompilerBarrier()

Definition at line 258 of file SDL_atomic.h.

◆ SDL_MemoryBarrierRelease

#define SDL_MemoryBarrierRelease ( )    SDL_CompilerBarrier()

Definition at line 257 of file SDL_atomic.h.

Typedef Documentation

◆ SDL_SpinLock

typedef int SDL_SpinLock

CategoryAtomic

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. An atomic spinlock.

The atomic locks are efficient spinlocks using CPU instructions, but are vulnerable to starvation and can spin forever if a thread holding a lock has been terminated. For this reason you should minimize the code executed inside an atomic lock and never do expensive things like API or system calls while holding them.

They are also vulnerable to starvation if the thread holding the lock is lower priority than other threads and doesn't get scheduled. In general you should use mutexes instead, since they have better performance and contention behavior.

The atomic locks are not safe to lock recursively.

Porting Note: The spin lock functions and type are required and can not be emulated because they are used in the atomic emulation code.

Definition at line 82 of file SDL_atomic.h.

Function Documentation

◆ SDL_AtomicAdd()

int SDL_AtomicAdd ( SDL_AtomicInt a,
int  v 
)
extern

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!

Parameters
aa pointer to an SDL_AtomicInt variable to be modified.
vthe desired value to add.
Returns
the previous value of the atomic variable.

\threadsafety It is safe to call this function from any thread.

Since
This function is available since SDL 3.0.0.
See also
SDL_AtomicDecRef
SDL_AtomicIncRef

◆ SDL_AtomicCompareAndSwap()

SDL_bool SDL_AtomicCompareAndSwap ( SDL_AtomicInt a,
int  oldval,
int  newval 
)
extern

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!

Parameters
aa pointer to an SDL_AtomicInt variable to be modified.
oldvalthe old value.
newvalthe new value.
Returns
SDL_TRUE if the atomic variable was set, SDL_FALSE otherwise.

\threadsafety It is safe to call this function from any thread.

Since
This function is available since SDL 3.0.0.
See also
SDL_AtomicCompareAndSwapPointer

◆ SDL_AtomicCompareAndSwapPointer()

SDL_bool SDL_AtomicCompareAndSwapPointer ( void **  a,
void *  oldval,
void *  newval 
)
extern

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!

Parameters
aa pointer to a pointer.
oldvalthe old pointer value.
newvalthe new pointer value.
Returns
SDL_TRUE if the pointer was set, SDL_FALSE otherwise.

\threadsafety It is safe to call this function from any thread.

Since
This function is available since SDL 3.0.0.
See also
SDL_AtomicCompareAndSwap
SDL_AtomicGetPtr
SDL_AtomicSetPtr

◆ SDL_AtomicGet()

int SDL_AtomicGet ( SDL_AtomicInt a)
extern

Get the value of an atomic variable.

Note: If you don't know what this function is for, you shouldn't use it!

Parameters
aa pointer to an SDL_AtomicInt variable.
Returns
the current value of an atomic variable.

\threadsafety It is safe to call this function from any thread.

Since
This function is available since SDL 3.0.0.
See also
SDL_AtomicSet

◆ SDL_AtomicGetPtr()

void * SDL_AtomicGetPtr ( void **  a)
extern

Get the value of a pointer atomically.

Note: If you don't know what this function is for, you shouldn't use it!

Parameters
aa pointer to a pointer.
Returns
the current value of a pointer.

\threadsafety It is safe to call this function from any thread.

Since
This function is available since SDL 3.0.0.
See also
SDL_AtomicCompareAndSwapPointer
SDL_AtomicSetPtr

◆ SDL_AtomicSet()

int SDL_AtomicSet ( SDL_AtomicInt a,
int  v 
)
extern

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!

Parameters
aa pointer to an SDL_AtomicInt variable to be modified.
vthe desired value.
Returns
the previous value of the atomic variable.

\threadsafety It is safe to call this function from any thread.

Since
This function is available since SDL 3.0.0.
See also
SDL_AtomicGet

◆ SDL_AtomicSetPtr()

void * SDL_AtomicSetPtr ( void **  a,
void *  v 
)
extern

Set a pointer to a value atomically.

Note: If you don't know what this function is for, you shouldn't use it!

Parameters
aa pointer to a pointer.
vthe desired pointer value.
Returns
the previous value of the pointer.

\threadsafety It is safe to call this function from any thread.

Since
This function is available since SDL 3.0.0.
See also
SDL_AtomicCompareAndSwapPointer
SDL_AtomicGetPtr

◆ SDL_LockSpinlock()

void SDL_LockSpinlock ( SDL_SpinLock lock)
extern

Lock a spin lock by setting it to a non-zero value.

Please note that spinlocks are dangerous if you don't know what you're doing. Please be careful using any sort of spinlock!

Parameters
locka pointer to a lock variable.
Since
This function is available since SDL 3.0.0.
See also
SDL_TryLockSpinlock
SDL_UnlockSpinlock

◆ SDL_MemoryBarrierAcquireFunction()

void SDL_MemoryBarrierAcquireFunction ( void  )
extern

Insert a memory acquire barrier.

Please refer to SDL_MemoryBarrierReleaseFunction for the details!

\threadsafety Obviously this function is safe to use from any thread at any time, but if you find yourself needing this, you are probably dealing with some very sensitive code; be careful!

Since
This function is available since SDL 3.0.0.
See also
SDL_MemoryBarrierReleaseFunction

◆ SDL_MemoryBarrierReleaseFunction()

void SDL_MemoryBarrierReleaseFunction ( void  )
extern

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

\threadsafety Obviously this macro is safe to use from any thread at any time, but if you find yourself needing this, you are probably dealing with some very sensitive code; be careful!

Since
This function is available since SDL 3.0.0.

◆ SDL_TryLockSpinlock()

SDL_bool SDL_TryLockSpinlock ( SDL_SpinLock lock)
extern

Try to lock a spin lock by setting it to a non-zero value.

Please note that spinlocks are dangerous if you don't know what you're doing. Please be careful using any sort of spinlock!

Parameters
locka pointer to a lock variable.
Returns
SDL_TRUE if the lock succeeded, SDL_FALSE if the lock is already held.
Since
This function is available since SDL 3.0.0.
See also
SDL_LockSpinlock
SDL_UnlockSpinlock

◆ SDL_UnlockSpinlock()

void SDL_UnlockSpinlock ( SDL_SpinLock lock)
extern

Unlock a spin lock by setting it to 0.

Always returns immediately.

Please note that spinlocks are dangerous if you don't know what you're doing. Please be careful using any sort of spinlock!

Parameters
locka pointer to a lock variable.
Since
This function is available since SDL 3.0.0.
See also
SDL_LockSpinlock
SDL_TryLockSpinlock