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