Skip to content

Instantly share code, notes, and snippets.

@facontidavide
Created March 8, 2017 12:34
Show Gist options
  • Save facontidavide/764f685e8cf0490ce6d9ed5f5553a9ec to your computer and use it in GitHub Desktop.
Save facontidavide/764f685e8cf0490ce6d9ed5f5553a9ec to your computer and use it in GitHub Desktop.
ReadWrite SpinLock
#ifndef RW_SPINLOCK_H
#define RW_SPINLOCK_H
#include<atomic>
#include<cassert>
#define SPIN_LOCK_UNLOCK 0
#define SPIN_LOCK_WRITE_LOCK -1
using std::memory_order_relaxed;
using std::memory_order_acquire;
using std::memory_order_release;
#define spinlock_t atomic<int>
//typedef atomic_int spinlock_t; // why not work?
struct SpinLock
{
SpinLock(){
std::atomic_store_explicit(&_atomic, SPIN_LOCK_UNLOCK, memory_order_relaxed);
}
std::atomic<int> _atomic;
};
struct ReadLock
{
SpinLock& _spinlock;
ReadLock(SpinLock& spinlock): _spinlock(spinlock) {}
void lock()
{
int expected, desired;
while(true){
expected = atomic_load_explicit(&_spinlock._atomic, memory_order_relaxed);
if(expected >= 0) {
desired = 1 + expected;
if(std::atomic_compare_exchange_weak_explicit(&_spinlock._atomic, &expected, desired, memory_order_relaxed, memory_order_relaxed))
break; // success
}
}
atomic_thread_fence(memory_order_acquire);
}
void unlock()
{
int expected, desired;
while(true) {
expected = std::atomic_load_explicit(&_spinlock._atomic, memory_order_relaxed);
if(expected > 0) {
desired = expected - 1;
std::atomic_thread_fence(memory_order_release); // sync
if(std::atomic_compare_exchange_weak_explicit(&_spinlock._atomic, &expected, desired, memory_order_relaxed, memory_order_relaxed))
break; // success
}
else{
assert(false);
}
}
}
};
struct WriteLock
{
SpinLock& _spinlock;
WriteLock(SpinLock& spinlock): _spinlock(spinlock) {}
void lock()
{
int expected, desired;
while(true) {
expected = std::atomic_load_explicit(&_spinlock._atomic, memory_order_relaxed);
if(expected == SPIN_LOCK_UNLOCK) {
desired = SPIN_LOCK_WRITE_LOCK;
if(std::atomic_compare_exchange_weak_explicit(&_spinlock._atomic, &expected, desired, memory_order_relaxed, memory_order_relaxed))
break; // success
}
}
std::atomic_thread_fence(memory_order_release); // sync
}
void unlock()
{
int expected, desired;
while(true) {
expected = std::atomic_load_explicit(&_spinlock._atomic, memory_order_relaxed);
if(expected == SPIN_LOCK_WRITE_LOCK) {
desired = SPIN_LOCK_UNLOCK;
std::atomic_thread_fence(memory_order_release); // sync
if(std::atomic_compare_exchange_weak_explicit(&_spinlock._atomic, &expected, desired, memory_order_relaxed, memory_order_relaxed))
break; // success
}
else {
assert(false);
}
}
}
};
#endif // RW_SPINLOCK_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment