1 /* 2 * Copyright (c) 2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef COMMON_COMPONENTS_BASE_RWLOCK_H 17 #define COMMON_COMPONENTS_BASE_RWLOCK_H 18 19 #include <atomic> 20 #include <pthread.h> 21 22 #include "common_components/log/log.h" 23 24 namespace common { 25 class RwLock { 26 public: LockRead()27 void LockRead() 28 { 29 int count = lockCount_.load(std::memory_order_acquire); 30 do { 31 while (count == WRITE_LOCKED) { 32 sched_yield(); 33 count = lockCount_.load(std::memory_order_acquire); 34 } 35 } while (!lockCount_.compare_exchange_weak(count, count + 1, std::memory_order_release)); 36 } 37 LockWrite()38 void LockWrite() 39 { 40 for (int count = 0; !lockCount_.compare_exchange_weak(count, WRITE_LOCKED, std::memory_order_release); 41 count = 0) { 42 sched_yield(); 43 } 44 } 45 TryLockWrite()46 bool TryLockWrite() 47 { 48 int count = 0; 49 if (lockCount_.compare_exchange_weak(count, WRITE_LOCKED, std::memory_order_release)) { 50 return true; 51 } 52 return false; 53 } 54 TryLockRead()55 bool TryLockRead() 56 { 57 int count = lockCount_.load(std::memory_order_acquire); 58 do { 59 if (count == WRITE_LOCKED) { 60 return false; 61 } 62 } while (!lockCount_.compare_exchange_weak(count, count + 1, std::memory_order_release)); 63 return true; 64 } 65 UnlockRead()66 void UnlockRead() 67 { 68 int count = lockCount_.fetch_sub(1); 69 if (count < 0) { //LCOV_EXCL_BR_LINE 70 LOG_COMMON(FATAL) << "Unresolved fatal"; 71 UNREACHABLE_CC(); 72 } 73 } 74 UnlockWrite()75 void UnlockWrite() 76 { 77 CHECK_CC(lockCount_.load() == WRITE_LOCKED); 78 lockCount_.store(0, std::memory_order_release); 79 } 80 81 private: 82 // 0: unlocked 83 // -1: write locked 84 // inc 1 for each read lock 85 static constexpr int WRITE_LOCKED = -1; 86 std::atomic<int> lockCount_{ 0 }; 87 }; 88 } // namespace common 89 #endif // COMMON_COMPONENTS_BASE_SPINLOCK_H 90