Reorgs added benchmarks (put them in misc folder)
[libcds.git] / cds / misc / seqlock.h
1 #ifndef _SEQLOCK_H
2 #define _SEQLOCK_H
3
4 #include "backoff.h"
5 #include <atomic>
6
7 namespace cds_others {
8
9 using std::atomic_int;
10 using std::memory_order_release;
11 using std::memory_order_acquire;
12 using std::memory_order_relaxed;
13
14 class SeqLock {
15 private:
16   // Sequence for reader consistency check.
17   atomic_int seq_;
18   // It needs to be atomic to avoid data races
19   atomic_int data_;
20
21 public:
22   SeqLock() {
23     atomic_init(&seq_, 0);
24     atomic_init(&data_, 0);
25   }
26
27   int read() {
28     ExpBackoff backoff;
29     while (true) {
30       int old_seq = seq_.load(memory_order_acquire);
31       if (old_seq % 2 == 1) {
32         backoff();
33         continue;
34       }
35
36       int res = data_.load(memory_order_acquire);
37       if (seq_.load(memory_order_relaxed) == old_seq) {
38         return res;
39       }
40     }
41   }
42
43   void write(int new_data) {
44     ExpBackoff backoff;
45     while (true) {
46       // This might be a relaxed too
47       int old_seq = seq_.load(memory_order_acquire);
48       if (old_seq % 2 == 1) {
49         backoff();
50         continue; // Retry
51       }
52
53       // Should be relaxed!!!
54       if (seq_.compare_exchange_strong(old_seq, old_seq + 1,
55                                        memory_order_relaxed,
56                                        memory_order_relaxed)) {
57         break;
58       }
59     }
60
61     // Update the data
62     data_.store(new_data, memory_order_release); // release
63
64     seq_.fetch_add(1, memory_order_release); // release
65   }
66 };
67
68 } // namespace cds_others
69
70 #endif