Adds misc benchmarks
[libcds.git] / cds / sync / seqlock.h
diff --git a/cds/sync/seqlock.h b/cds/sync/seqlock.h
new file mode 100644 (file)
index 0000000..a84c0c4
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef _SEQLOCK_H
+#define _SEQLOCK_H
+
+#include <atomic>
+
+namespace cds_others {
+
+using std::atomic_int;
+using std::memory_order_release;
+using std::memory_order_acquire;
+using std::memory_order_relaxed;
+
+class SeqLock {
+private:
+  // Sequence for reader consistency check.
+  atomic_int seq_;
+  // It needs to be atomic to avoid data races
+  atomic_int data_;
+
+public:
+  SeqLock() {
+    atomic_init(&seq_, 0);
+    atomic_init(&data_, 0);
+  }
+
+  int read() {
+    while (true) {
+      int old_seq = seq_.load(memory_order_acquire); // acquire
+      if (old_seq % 2 == 1)
+        continue;
+
+      int res = data_.load(memory_order_acquire);       // acquire
+      if (seq_.load(memory_order_relaxed) == old_seq) { // relaxed
+        return res;
+      }
+    }
+  }
+
+  void write(int new_data) {
+    while (true) {
+      // This might be a relaxed too
+      int old_seq = seq_.load(memory_order_acquire); // acquire
+      if (old_seq % 2 == 1)
+        continue; // Retry
+
+      // Should be relaxed!!!
+      if (seq_.compare_exchange_strong(old_seq, old_seq + 1,
+                                       memory_order_relaxed,
+                                       memory_order_relaxed)) // relaxed
+        break;
+    }
+
+    // Update the data
+    data_.store(new_data, memory_order_release); // release
+
+    seq_.fetch_add(1, memory_order_release); // release
+  }
+};
+
+} // namespace cds_others
+
+#endif