Atomic Operations

Last Updated 6/19/19
Semaphores operate at an operating system level. Atomic operations are a way to lock data at an efficient CPU level. Here we'll be locking a critical section using CPU spinlocks.//Data access spin lock
SDL_SpinLock gDataLock = 0;
//The "data buffer"
int gData = -1;
Instead of a semaphore we'll be using a spinlock to protect our data buffer.
bool loadMedia()
{
//Loading success flag
bool success = true;
//Load splash texture
if( !gSplashTexture.loadFromFile( "48_atomic_operations/splash.png" ) )
{
printf( "Failed to load splash texture!\n" );
success = false;
}
return success;
}
void close()
{
//Free loaded images
gSplashTexture.free();
//Destroy window
SDL_DestroyRenderer( gRenderer );
SDL_DestroyWindow( gWindow );
gWindow = NULL;
gRenderer = NULL;
//Quit SDL subsystems
IMG_Quit();
SDL_Quit();
}
Unlike semaphores, spin locks do not need to be allocated and deallocated.
int worker( void* data )
{
printf( "%s starting...\n", data );
//Pre thread random seeding
srand( SDL_GetTicks() );
//Work 5 times
for( int i = 0; i < 5; ++i )
{
//Wait randomly
SDL_Delay( 16 + rand() % 32 );
//Lock
SDL_AtomicLock( &gDataLock );
//Print pre work data
printf( "%s gets %d\n", data, gData );
//"Work"
gData = rand() % 256;
//Print post work data
printf( "%s sets %d\n\n", data, gData );
//Unlock
SDL_AtomicUnlock( &gDataLock );
//Wait randomly
SDL_Delay( 16 + rand() % 640 );
}
printf( "%s finished!\n\n", data );
return 0;
}
Here our critical section is protected by SDL_AtomicLock and
SDL_AtomicUnlock.
In this case it may seem like semaphores and atomic locks are the same, but remember that semaphores can allow access beyond a single thread. Atomic operations are for when you want a strict locked/unlocked state.
In this case it may seem like semaphores and atomic locks are the same, but remember that semaphores can allow access beyond a single thread. Atomic operations are for when you want a strict locked/unlocked state.