Skip to content

Instantly share code, notes, and snippets.

@jac18281828
Last active September 30, 2017 23:33
Show Gist options
  • Save jac18281828/71899c186f93ca032cf258ce42395e5f to your computer and use it in GitHub Desktop.
Save jac18281828/71899c186f93ca032cf258ce42395e5f to your computer and use it in GitHub Desktop.
Hans-J. Boehm sequence lock in c++
#pragma once
#include <stdatomic.h>
#include <atomic>
#include <sys/types.h>
#define PAUSE asm volatile("pause\n": : :"memory");
class seq_lock {
private:
std::atomic<size_t> sequence;
public:
seq_lock() {
sequence.store(2L, std::memory_order_relaxed);
}
size_t read_lock() {
return sequence.load(std::memory_order_acquire);
}
bool read_lock_held(size_t lock_token) {
std::atomic_thread_fence(std::memory_order_acquire);
size_t const seq = sequence.load(std::memory_order_relaxed);
return seq == lock_token && (lock_token & 1L) == 0L;
}
size_t write_lock() {
size_t seq0 = sequence.load(std::memory_order_acquire);
// lock acquire
for(;;) {
if((seq0 & 1) == 0 &&
sequence.compare_exchange_weak(seq0, seq0 + 1)) {
return seq0;
}
PAUSE
}
}
size_t try_write_lock() {
size_t seq0 = sequence.load(std::memory_order_acquire);
// lock acquire
if((seq0 & 1) == 0 &&
sequence.compare_exchange_weak(seq0, seq0 + 1)) {
return seq0;
}
return 0;
}
void unlock(size_t lock_token) {
sequence.store(lock_token + 2, std::memory_order_release);
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment