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