Software Developer

Subscribe

© 2022

std::atomic - C++11 spinlock implementation

Spinlock is a synchronization mechanism that waits in a loop to acquire the lock. This kind of lock is busy waiting. It consumes processor time, doing an empty loop, so it may seem like an inefficient mechanism. In multiprocessor systems, spinlock can sometimes be more efficient than mutexes, because the loop is executing in the userspace context. Time-consuming context switching to system code is avoided. Spinlocks works great when threads are blocked only for short periods.

std::atomic_flag is an atomic boolean flag that is guaranteed to be lock-free.

#include <atomic>

std::atomic_flag lock = ATOMIC_FLAG_INIT;

void foo()
{
    while (lock.test_and_set(std::memory_order_acquire))    // lock
        ;

    // do something...

    lock.clear(std::memory_order_release);  // unlock
}

Scoped block spinlock

I created RAII-style mechanism for owning a spinlock for the duration of a scoped block.

#include <atomic>
#include <iostream>

// lock created somewhere in global or thread shared space
std::atomic_flag lock = ATOMIC_FLAG_INIT;

class ScopedSpinlock
{
private:
    std::atomic_flag& lock;

public:
    explicit ScopedSpinlock(std::atomic_flag& l) : lock(l)
    {
        while (this->lock.test_and_set(std::memory_order_acquire))    // lock
            ;   // spin
    }

    ~ScopedSpinlock()
    {
        this->lock.clear(std::memory_order_release);
    }
};

int protectedVariable = 5;

// usage example
void foo()
{
    ScopedSpinlock guard(lock);

    ++protectedVariable;
    std::cout << "Protected variable value: " << protectedVariable << std::endl;

    // end of scope 
    // lock is released automatically by ScopedSpinlock destructor
}