Refactors lock test cases backoff values
[libcds.git] / cds / misc / rwlock.h
1 #ifndef _RWLOCK_H
2 #define _RWLOCK_H
3
4 #include "backoff.h"
5 #include <atomic>
6 #include <cds/algo/backoff_strategy.h>
7 #include <thread>
8
9 namespace cds_others {
10
11 #define RW_LOCK_BIAS 0x00100000
12 #define WRITE_LOCK_CMP RW_LOCK_BIAS
13
14 using std::memory_order_acquire;
15 using std::memory_order_release;
16 using std::memory_order_relaxed;
17 using std::atomic_int;
18
19 class RWLock {
20 public:
21   RWLock() {
22     lock.store(RW_LOCK_BIAS);
23   }
24
25   int read_can_lock() {
26     return atomic_load_explicit(&lock, memory_order_relaxed) > 0;
27   }
28
29   int write_can_lock() {
30     return atomic_load_explicit(&lock, memory_order_relaxed) == RW_LOCK_BIAS;
31   }
32
33   void read_lock() {
34     ExpBackoff backoff;
35     int priorvalue = atomic_fetch_sub_explicit(&lock, 1, memory_order_acquire);
36     while (priorvalue <= 0) {
37       atomic_fetch_add_explicit(&lock, 1, memory_order_relaxed);
38       while (atomic_load_explicit(&lock, memory_order_relaxed) <= 0) {
39         backoff();
40       }
41       priorvalue = atomic_fetch_sub_explicit(&lock, 1, memory_order_acquire);
42     }
43   }
44
45   void write_lock() {
46     int priorvalue =
47         atomic_fetch_sub_explicit(&lock, RW_LOCK_BIAS, memory_order_acquire);
48     ExpBackoff backoff;
49     while (priorvalue != RW_LOCK_BIAS) {
50       atomic_fetch_add_explicit(&lock, RW_LOCK_BIAS, memory_order_relaxed);
51       while (atomic_load_explicit(&lock, memory_order_relaxed) !=
52              RW_LOCK_BIAS) {
53         backoff();
54       }
55       priorvalue =
56           atomic_fetch_sub_explicit(&lock, RW_LOCK_BIAS, memory_order_acquire);
57     }
58   }
59
60   int read_trylock() {
61     int priorvalue = atomic_fetch_sub_explicit(&lock, 1, memory_order_acquire);
62     if (priorvalue > 0)
63       return 1;
64
65     atomic_fetch_add_explicit(&lock, 1, memory_order_relaxed);
66     return 0;
67   }
68
69   int write_trylock() {
70     int priorvalue =
71         atomic_fetch_sub_explicit(&lock, RW_LOCK_BIAS, memory_order_acquire);
72     if (priorvalue == RW_LOCK_BIAS)
73       return 1;
74
75     atomic_fetch_add_explicit(&lock, RW_LOCK_BIAS, memory_order_relaxed);
76     return 0;
77   }
78
79   void read_unlock() {
80     atomic_fetch_add_explicit(&lock, 1, memory_order_release);
81   }
82
83   void write_unlock() {
84     atomic_fetch_add_explicit(&lock, RW_LOCK_BIAS, memory_order_release);
85   }
86
87 private:
88   atomic_int lock;
89 };
90
91 } // namespace cds_others
92
93 #endif