1/* 2 * Copyright (c) 2021 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#include "rwlock.h" 17#include <cassert> 18 19namespace OHOS { 20namespace Utils { 21 22RWLock::RWLock(bool writeFirst) 23 : writeFirst_(writeFirst), writeThreadID_(), lockCount_(0), writeWaitCount_(0) 24{ 25} 26 27void RWLock::LockRead() 28{ 29 // If the thread has obtained the write lock, return directly. 30 if (std::this_thread::get_id() == writeThreadID_) { 31 return; 32 } 33 34 int count; 35 if (writeFirst_) { 36 do { 37 // In write priority mode, the state must be non-write locked and no other threads are waiting to write 38 while ((count = lockCount_) == LOCK_STATUS_WRITE || writeWaitCount_ > 0) {} 39 } while (!lockCount_.compare_exchange_weak(count, count + 1)); 40 } else { 41 do { 42 // If it is not write priority, you only need the current state to be non-write-locked. 43 while ((count = lockCount_) == LOCK_STATUS_WRITE) {} 44 } while (!lockCount_.compare_exchange_weak(count, count + 1)); 45 } 46} 47 48void RWLock::UnLockRead() 49{ 50 // Supports the case of writing and reading nesting. 51 // If the write lock has been obtained before, the read lock is directly returned successfully, 52 // and then the thread is still directly returned when unlocking. 53 if (std::this_thread::get_id() != writeThreadID_) { 54 --lockCount_; 55 } 56} 57 58void RWLock::LockWrite() 59{ 60 // If this thread is already a thread that gets the write lock, return directly to avoid repeated locks. 61 if (std::this_thread::get_id() != writeThreadID_) { 62 ++writeWaitCount_; // Write wait counter plus 1 63 64 // Only when no thread has acquired a read lock or a write lock (the lock counter status is FREE) 65 // can the write lock be acquired and the counter set to WRITE; otherwise wait 66 for (int status = LOCK_STATUS_FREE; !lockCount_.compare_exchange_weak(status, LOCK_STATUS_WRITE); 67 status = LOCK_STATUS_FREE) { 68 } 69 70 // After the write lock is successfully acquired, the write wait counter is decremented by 1. 71 --writeWaitCount_; 72 writeThreadID_ = std::this_thread::get_id(); 73 } 74} 75 76void RWLock::UnLockWrite() 77{ 78 if (std::this_thread::get_id() != writeThreadID_) { 79 return; 80 } 81 82 if (lockCount_ != LOCK_STATUS_WRITE) { 83 return; 84 } 85 86 writeThreadID_ = std::thread::id(); 87 lockCount_.store(LOCK_STATUS_FREE); 88} 89 90} // namespace Utils 91} // namespace OHOS 92