Created
March 8, 2017 12:34
-
-
Save facontidavide/764f685e8cf0490ce6d9ed5f5553a9ec to your computer and use it in GitHub Desktop.
ReadWrite SpinLock
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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