17#ifndef CYBER_BASE_REENTRANT_RW_LOCK_H_
18#define CYBER_BASE_REENTRANT_RW_LOCK_H_
23#include <condition_variable>
36static const std::thread::id NULL_THREAD_ID = std::thread::id();
59 std::thread::id write_thread_id_ = {NULL_THREAD_ID};
60 std::atomic<uint32_t> write_lock_wait_num_ = {0};
61 std::atomic<int32_t> lock_num_ = {0};
62 bool write_first_ =
true;
65inline void ReentrantRWLock::ReadLock() {
66 if (write_thread_id_ == std::this_thread::get_id()) {
70 uint32_t retry_times = 0;
71 int32_t lock_num = lock_num_.load(std::memory_order_acquire);
75 write_lock_wait_num_.load(std::memory_order_acquire) > 0) {
78 std::this_thread::yield();
81 lock_num = lock_num_.load(std::memory_order_acquire);
83 }
while (!lock_num_.compare_exchange_weak(lock_num, lock_num + 1,
84 std::memory_order_acq_rel,
85 std::memory_order_relaxed));
91 std::this_thread::yield();
94 lock_num = lock_num_.load(std::memory_order_acquire);
96 }
while (!lock_num_.compare_exchange_weak(lock_num, lock_num + 1,
97 std::memory_order_acq_rel,
98 std::memory_order_relaxed));
102inline void ReentrantRWLock::WriteLock() {
103 auto this_thread_id = std::this_thread::get_id();
104 if (write_thread_id_ == this_thread_id) {
105 lock_num_.fetch_sub(1);
109 uint32_t retry_times = 0;
110 write_lock_wait_num_.fetch_add(1);
112 std::memory_order_acq_rel,
113 std::memory_order_relaxed)) {
118 std::this_thread::yield();
122 write_thread_id_ = this_thread_id;
123 write_lock_wait_num_.fetch_sub(1);
126inline void ReentrantRWLock::ReadUnlock() {
127 if (write_thread_id_ == std::this_thread::get_id()) {
130 lock_num_.fetch_sub(1);
133inline void ReentrantRWLock::WriteUnlock() {
135 write_thread_id_ = NULL_THREAD_ID;
static const int32_t RW_LOCK_FREE
ReentrantRWLock(bool write_first)
static const std::thread::id null_thread
static const uint32_t MAX_RETRY_TIMES
static const int32_t WRITE_EXCLUSIVE