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 #ifndef FOUNDATION_ACE_FRAMEWORKS_BASE_MEMORY_REF_COUNTER_H 17 #define FOUNDATION_ACE_FRAMEWORKS_BASE_MEMORY_REF_COUNTER_H 18 19 #include <atomic> 20 21 #include "base/utils/macros.h" 22 #include "base/utils/noncopyable.h" 23 24 namespace OHOS::Ace { 25 26 // Reference counter. 27 class RefCounter { 28 public: 29 virtual void IncStrongRef() = 0; 30 virtual int32_t DecStrongRef() = 0; 31 virtual bool TryIncStrongRef() = 0; 32 virtual int32_t StrongRefCount() const = 0; 33 virtual void IncWeakRef() = 0; 34 virtual void DecWeakRef() = 0; 35 36 protected: 37 virtual ~RefCounter() = default; 38 }; 39 40 // Define thread-safe counter using 'std::atomic' to implement Increase/Decrease count. 41 class ThreadSafeCounter final { 42 public: ThreadSafeCounter(int32_t count)43 explicit ThreadSafeCounter(int32_t count) : count_(count) {} 44 ~ThreadSafeCounter() = default; 45 Increase()46 void Increase() 47 { 48 count_.fetch_add(1, std::memory_order_relaxed); 49 } Decrease()50 int32_t Decrease() 51 { 52 int32_t count = count_.fetch_sub(1, std::memory_order_release); 53 ACE_DCHECK(count > 0); 54 return count - 1; 55 } CurrentCount()56 int32_t CurrentCount() const 57 { 58 return count_.load(std::memory_order_relaxed); 59 } 60 61 // Try to increase reference count while current value is not zero. TryIncrease()62 bool TryIncrease() 63 { 64 int32_t count = CurrentCount(); 65 do { 66 if (count == 0) { 67 return false; 68 } 69 ACE_DCHECK(count > 0); 70 } while (!count_.compare_exchange_weak(count, count + 1, std::memory_order_relaxed)); 71 return true; 72 } 73 74 private: 75 std::atomic<int32_t> count_ { 0 }; 76 77 ACE_DISALLOW_COPY_AND_MOVE(ThreadSafeCounter); 78 }; 79 80 // Define thread-unsafe counter. 81 class ThreadUnsafeCounter final { 82 public: ThreadUnsafeCounter(int32_t count)83 explicit ThreadUnsafeCounter(int32_t count) : count_(count) {} 84 ~ThreadUnsafeCounter() = default; 85 Increase()86 void Increase() 87 { 88 ++count_; 89 } Decrease()90 int32_t Decrease() 91 { 92 int32_t count = --count_; 93 ACE_DCHECK(count >= 0); 94 return count; 95 } CurrentCount()96 int32_t CurrentCount() const 97 { 98 return count_; 99 } 100 101 // Try to increase count while current value is not zero. TryIncrease()102 bool TryIncrease() 103 { 104 if (CurrentCount() == 0) { 105 return false; 106 } 107 Increase(); 108 return true; 109 } 110 111 private: 112 int32_t count_ { 0 }; 113 114 ACE_DISALLOW_COPY_AND_MOVE(ThreadUnsafeCounter); 115 }; 116 117 template<class T> 118 class RefCounterImpl final : public RefCounter { 119 public: Create()120 static RefCounter* Create() 121 { 122 return new RefCounterImpl(); 123 } 124 IncStrongRef()125 void IncStrongRef() final 126 { 127 strongRef_.Increase(); 128 } DecStrongRef()129 int32_t DecStrongRef() final 130 { 131 return strongRef_.Decrease(); 132 } TryIncStrongRef()133 bool TryIncStrongRef() final 134 { 135 return strongRef_.TryIncrease(); 136 } StrongRefCount()137 int32_t StrongRefCount() const final 138 { 139 return strongRef_.CurrentCount(); 140 } 141 IncWeakRef()142 void IncWeakRef() final 143 { 144 weakRef_.Increase(); 145 } DecWeakRef()146 void DecWeakRef() final 147 { 148 int32_t refCount = weakRef_.Decrease(); 149 if (refCount == 0) { 150 // Release this reference counter, while its weak reference have reduced to zero. 151 delete this; 152 } 153 } 154 155 private: 156 T strongRef_ { 0 }; 157 // Weak reference count should start with 1, 158 // because instance MUST hold the reference counter for itself. 159 T weakRef_ { 1 }; 160 }; 161 162 using ThreadSafeRef = RefCounterImpl<ThreadSafeCounter>; 163 using ThreadUnsafeRef = RefCounterImpl<ThreadUnsafeCounter>; 164 165 } // namespace OHOS::Ace 166 167 #endif // FOUNDATION_ACE_FRAMEWORKS_BASE_MEMORY_REF_COUNTER_H 168