1e9297d28Sopenharmony_ci/* 2e9297d28Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3e9297d28Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4e9297d28Sopenharmony_ci * you may not use this file except in compliance with the License. 5e9297d28Sopenharmony_ci * You may obtain a copy of the License at 6e9297d28Sopenharmony_ci * 7e9297d28Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8e9297d28Sopenharmony_ci * 9e9297d28Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10e9297d28Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11e9297d28Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12e9297d28Sopenharmony_ci * See the License for the specific language governing permissions and 13e9297d28Sopenharmony_ci * limitations under the License. 14e9297d28Sopenharmony_ci */ 15e9297d28Sopenharmony_ci 16e9297d28Sopenharmony_ci#include "refbase.h" 17e9297d28Sopenharmony_ci#ifdef DEBUG_REFBASE 18e9297d28Sopenharmony_ci#include "utils_log.h" 19e9297d28Sopenharmony_ci#include <unistd.h> 20e9297d28Sopenharmony_ci#endif 21e9297d28Sopenharmony_ci 22e9297d28Sopenharmony_cinamespace OHOS { 23e9297d28Sopenharmony_ci 24e9297d28Sopenharmony_ciWeakRefCounter::WeakRefCounter(RefCounter *counter, void *cookie) 25e9297d28Sopenharmony_ci : atomicWeak_(0), refCounter_(counter), cookie_(cookie) 26e9297d28Sopenharmony_ci{ 27e9297d28Sopenharmony_ci if (refCounter_ != nullptr) { 28e9297d28Sopenharmony_ci refCounter_->IncRefCount(); 29e9297d28Sopenharmony_ci } 30e9297d28Sopenharmony_ci} 31e9297d28Sopenharmony_ci 32e9297d28Sopenharmony_ciWeakRefCounter::~WeakRefCounter() 33e9297d28Sopenharmony_ci{ 34e9297d28Sopenharmony_ci if (refCounter_ != nullptr) { 35e9297d28Sopenharmony_ci refCounter_->DecRefCount(); 36e9297d28Sopenharmony_ci } 37e9297d28Sopenharmony_ci} 38e9297d28Sopenharmony_ci 39e9297d28Sopenharmony_ciint WeakRefCounter::GetWeakRefCount() const 40e9297d28Sopenharmony_ci{ 41e9297d28Sopenharmony_ci return atomicWeak_.load(std::memory_order_relaxed); 42e9297d28Sopenharmony_ci} 43e9297d28Sopenharmony_ci 44e9297d28Sopenharmony_civoid* WeakRefCounter::GetRefPtr() 45e9297d28Sopenharmony_ci{ 46e9297d28Sopenharmony_ci if ((cookie_ != nullptr) && (!refCounter_->IsRefPtrValid())) { 47e9297d28Sopenharmony_ci cookie_ = nullptr; 48e9297d28Sopenharmony_ci } 49e9297d28Sopenharmony_ci return cookie_; 50e9297d28Sopenharmony_ci} 51e9297d28Sopenharmony_ci 52e9297d28Sopenharmony_civoid WeakRefCounter::IncWeakRefCount(const void *objectId) 53e9297d28Sopenharmony_ci{ 54e9297d28Sopenharmony_ci if (atomicWeak_.fetch_add(1, std::memory_order_relaxed) == 0) { 55e9297d28Sopenharmony_ci refCounter_->IncWeakRefCount(objectId); 56e9297d28Sopenharmony_ci } 57e9297d28Sopenharmony_ci} 58e9297d28Sopenharmony_ci 59e9297d28Sopenharmony_civoid WeakRefCounter::DecWeakRefCount(const void *objectId) 60e9297d28Sopenharmony_ci{ 61e9297d28Sopenharmony_ci if (atomicWeak_.fetch_sub(1, std::memory_order_release) == 1) { 62e9297d28Sopenharmony_ci refCounter_->DecWeakRefCount(objectId); 63e9297d28Sopenharmony_ci delete this; 64e9297d28Sopenharmony_ci } 65e9297d28Sopenharmony_ci} 66e9297d28Sopenharmony_ci 67e9297d28Sopenharmony_cibool WeakRefCounter::AttemptIncStrongRef(const void *objectId) 68e9297d28Sopenharmony_ci{ 69e9297d28Sopenharmony_ci int unuse = 0; 70e9297d28Sopenharmony_ci return refCounter_->AttemptIncStrongRef(objectId, unuse); 71e9297d28Sopenharmony_ci} 72e9297d28Sopenharmony_ci 73e9297d28Sopenharmony_ci#ifdef DEBUG_REFBASE 74e9297d28Sopenharmony_ciRefTracker::RefTracker(RefTracker* exTracker, const void* id, int strong, int weak, int ref, int pid, int tid) 75e9297d28Sopenharmony_ci : ptrID (id), strongRefCNT (strong), weakRefCNT (weak), refCNT (ref), PID (pid), TID (tid), exTrace (exTracker) 76e9297d28Sopenharmony_ci{ 77e9297d28Sopenharmony_ci} 78e9297d28Sopenharmony_ci 79e9297d28Sopenharmony_civoid RefTracker::GetTrace(RefTracker* exTracker, const void* id, int strong, int weak, int ref, int pid, int tid) 80e9297d28Sopenharmony_ci{ 81e9297d28Sopenharmony_ci ptrID = id; 82e9297d28Sopenharmony_ci strongRefCNT = strong; 83e9297d28Sopenharmony_ci weakRefCNT = weak; 84e9297d28Sopenharmony_ci refCNT = ref; 85e9297d28Sopenharmony_ci PID = pid; 86e9297d28Sopenharmony_ci TID = tid; 87e9297d28Sopenharmony_ci exTrace = exTracker; 88e9297d28Sopenharmony_ci} 89e9297d28Sopenharmony_ci 90e9297d28Sopenharmony_civoid RefTracker::GetStrongTrace(RefTracker* exTracker, const void* id, int strong, int pid, int tid) 91e9297d28Sopenharmony_ci{ 92e9297d28Sopenharmony_ci ptrID = id; 93e9297d28Sopenharmony_ci strongRefCNT = strong; 94e9297d28Sopenharmony_ci weakRefCNT = -(INITIAL_PRIMARY_VALUE); 95e9297d28Sopenharmony_ci refCNT = -(INITIAL_PRIMARY_VALUE); 96e9297d28Sopenharmony_ci PID = pid; 97e9297d28Sopenharmony_ci TID = tid; 98e9297d28Sopenharmony_ci exTrace = exTracker; 99e9297d28Sopenharmony_ci} 100e9297d28Sopenharmony_ci 101e9297d28Sopenharmony_civoid RefTracker::GetWeakTrace(RefTracker* exTracker, const void* id, int weak, int pid, int tid) 102e9297d28Sopenharmony_ci{ 103e9297d28Sopenharmony_ci ptrID = id; 104e9297d28Sopenharmony_ci strongRefCNT = -(INITIAL_PRIMARY_VALUE); 105e9297d28Sopenharmony_ci weakRefCNT = weak; 106e9297d28Sopenharmony_ci refCNT = -(INITIAL_PRIMARY_VALUE); 107e9297d28Sopenharmony_ci PID = pid; 108e9297d28Sopenharmony_ci TID = tid; 109e9297d28Sopenharmony_ci exTrace = exTracker; 110e9297d28Sopenharmony_ci} 111e9297d28Sopenharmony_ci 112e9297d28Sopenharmony_civoid RefTracker::PrintTrace(const void* root) 113e9297d28Sopenharmony_ci{ 114e9297d28Sopenharmony_ci UTILS_LOGI("ptrID(%{public}lx) call %{public}lx. strongcnt: %{public}d weakcnt: %{public}d " \ 115e9297d28Sopenharmony_ci "refcnt: %{public}d PID: %{public}d TID: %{public}d", 116e9297d28Sopenharmony_ci reinterpret_cast<size_t>(ptrID), reinterpret_cast<size_t>(root), strongRefCNT, weakRefCNT, refCNT, PID, TID); 117e9297d28Sopenharmony_ci} 118e9297d28Sopenharmony_ci 119e9297d28Sopenharmony_civoid RefTracker::PrintStrongTrace(const void* root) 120e9297d28Sopenharmony_ci{ 121e9297d28Sopenharmony_ci UTILS_LOGI("ptrID(%{public}lx) call %{public}lx. strongcnt: %{public}d PID: %{public}d TID: %{public}d", 122e9297d28Sopenharmony_ci reinterpret_cast<size_t>(ptrID), reinterpret_cast<size_t>(root), strongRefCNT, PID, TID); 123e9297d28Sopenharmony_ci} 124e9297d28Sopenharmony_ci 125e9297d28Sopenharmony_civoid RefTracker::PrintWeakTrace(const void* root) 126e9297d28Sopenharmony_ci{ 127e9297d28Sopenharmony_ci UTILS_LOGI("ptrID(%{public}lx) call %{public}lx. weakcnt: %{public}d PID: %{public}d TID: %{public}d", 128e9297d28Sopenharmony_ci reinterpret_cast<size_t>(ptrID), reinterpret_cast<size_t>(root), weakRefCNT, PID, TID); 129e9297d28Sopenharmony_ci} 130e9297d28Sopenharmony_ci 131e9297d28Sopenharmony_ciRefTracker* RefTracker::GetexTrace() 132e9297d28Sopenharmony_ci{ 133e9297d28Sopenharmony_ci return exTrace; 134e9297d28Sopenharmony_ci} 135e9297d28Sopenharmony_ci 136e9297d28Sopenharmony_ciRefTracker* RefTracker::PopTrace(const void* root) 137e9297d28Sopenharmony_ci{ 138e9297d28Sopenharmony_ci RefTracker* ref = exTrace; 139e9297d28Sopenharmony_ci PrintTrace(root); 140e9297d28Sopenharmony_ci delete this; 141e9297d28Sopenharmony_ci return ref; 142e9297d28Sopenharmony_ci} 143e9297d28Sopenharmony_ci 144e9297d28Sopenharmony_civoid RefCounter::GetNewTrace(const void* objectId) 145e9297d28Sopenharmony_ci{ 146e9297d28Sopenharmony_ci std::lock_guard<std::mutex> lock(trackerMutex); 147e9297d28Sopenharmony_ci RefTracker* newTracker = new RefTracker(refTracker, objectId, atomicStrong_.load(std::memory_order_relaxed), 148e9297d28Sopenharmony_ci atomicWeak_.load(std::memory_order_relaxed), atomicRefCount_.load(std::memory_order_relaxed), 149e9297d28Sopenharmony_ci getpid(), gettid()); 150e9297d28Sopenharmony_ci refTracker = newTracker; 151e9297d28Sopenharmony_ci} 152e9297d28Sopenharmony_ci 153e9297d28Sopenharmony_civoid RefCounter::PrintTracker() 154e9297d28Sopenharmony_ci{ 155e9297d28Sopenharmony_ci std::lock_guard<std::mutex> lock(trackerMutex); 156e9297d28Sopenharmony_ci while (refTracker) { 157e9297d28Sopenharmony_ci refTracker = refTracker->PopTrace(this); 158e9297d28Sopenharmony_ci } 159e9297d28Sopenharmony_ci} 160e9297d28Sopenharmony_ci#endif 161e9297d28Sopenharmony_ci 162e9297d28Sopenharmony_ciRefCounter::RefCounter() 163e9297d28Sopenharmony_ci : atomicStrong_(INITIAL_PRIMARY_VALUE), atomicWeak_(0), atomicRefCount_(0), atomicFlags_(0), atomicAttempt_(0) 164e9297d28Sopenharmony_ci{ 165e9297d28Sopenharmony_ci} 166e9297d28Sopenharmony_ci 167e9297d28Sopenharmony_ciint RefCounter::GetRefCount() 168e9297d28Sopenharmony_ci{ 169e9297d28Sopenharmony_ci return atomicRefCount_.load(std::memory_order_relaxed); 170e9297d28Sopenharmony_ci} 171e9297d28Sopenharmony_ci 172e9297d28Sopenharmony_civoid RefCounter::IncRefCount() 173e9297d28Sopenharmony_ci{ 174e9297d28Sopenharmony_ci atomicRefCount_.fetch_add(1, std::memory_order_relaxed); 175e9297d28Sopenharmony_ci} 176e9297d28Sopenharmony_ci 177e9297d28Sopenharmony_civoid RefCounter::DecRefCount() 178e9297d28Sopenharmony_ci{ 179e9297d28Sopenharmony_ci if (atomicRefCount_.load(std::memory_order_relaxed) > 0) { 180e9297d28Sopenharmony_ci if (atomicRefCount_.fetch_sub(1, std::memory_order_release) == 1) { 181e9297d28Sopenharmony_ci delete (this); 182e9297d28Sopenharmony_ci } 183e9297d28Sopenharmony_ci } 184e9297d28Sopenharmony_ci} 185e9297d28Sopenharmony_ci 186e9297d28Sopenharmony_civoid RefCounter::SetCallback(const RefPtrCallback& callback) 187e9297d28Sopenharmony_ci{ 188e9297d28Sopenharmony_ci callback_ = callback; 189e9297d28Sopenharmony_ci} 190e9297d28Sopenharmony_ci 191e9297d28Sopenharmony_civoid RefCounter::RemoveCallback() 192e9297d28Sopenharmony_ci{ 193e9297d28Sopenharmony_ci callback_ = nullptr; 194e9297d28Sopenharmony_ci} 195e9297d28Sopenharmony_ci 196e9297d28Sopenharmony_cibool RefCounter::IsRefPtrValid() 197e9297d28Sopenharmony_ci{ 198e9297d28Sopenharmony_ci return callback_ != nullptr; 199e9297d28Sopenharmony_ci} 200e9297d28Sopenharmony_ci 201e9297d28Sopenharmony_ciRefCounter::~RefCounter() 202e9297d28Sopenharmony_ci{ 203e9297d28Sopenharmony_ci#ifdef DEBUG_REFBASE 204e9297d28Sopenharmony_ci PrintTracker(); 205e9297d28Sopenharmony_ci#endif 206e9297d28Sopenharmony_ci} 207e9297d28Sopenharmony_ci 208e9297d28Sopenharmony_ciint RefCounter::IncStrongRefCount(const void* objectId) 209e9297d28Sopenharmony_ci{ 210e9297d28Sopenharmony_ci#ifdef DEBUG_REFBASE 211e9297d28Sopenharmony_ci GetNewTrace(objectId); 212e9297d28Sopenharmony_ci#endif 213e9297d28Sopenharmony_ci int curCount = atomicStrong_.load(std::memory_order_relaxed); 214e9297d28Sopenharmony_ci if (curCount >= 0) { 215e9297d28Sopenharmony_ci curCount = atomicStrong_.fetch_add(1, std::memory_order_relaxed); 216e9297d28Sopenharmony_ci if (curCount == INITIAL_PRIMARY_VALUE) { 217e9297d28Sopenharmony_ci atomicStrong_.fetch_sub(INITIAL_PRIMARY_VALUE, std::memory_order_release); 218e9297d28Sopenharmony_ci } 219e9297d28Sopenharmony_ci } 220e9297d28Sopenharmony_ci 221e9297d28Sopenharmony_ci return curCount; 222e9297d28Sopenharmony_ci} 223e9297d28Sopenharmony_ci 224e9297d28Sopenharmony_ciint RefCounter::DecStrongRefCount(const void* objectId) 225e9297d28Sopenharmony_ci{ 226e9297d28Sopenharmony_ci#ifdef DEBUG_REFBASE 227e9297d28Sopenharmony_ci GetNewTrace(objectId); 228e9297d28Sopenharmony_ci#endif 229e9297d28Sopenharmony_ci int curCount = GetStrongRefCount(); 230e9297d28Sopenharmony_ci if (curCount == INITIAL_PRIMARY_VALUE) { 231e9297d28Sopenharmony_ci // unexpected case: there had never a strong reference. 232e9297d28Sopenharmony_ci } else if (curCount > 0) { 233e9297d28Sopenharmony_ci // we should update the current count here. 234e9297d28Sopenharmony_ci // it may be changed after last operation. 235e9297d28Sopenharmony_ci curCount = atomicStrong_.fetch_sub(1, std::memory_order_release); 236e9297d28Sopenharmony_ci } 237e9297d28Sopenharmony_ci 238e9297d28Sopenharmony_ci return curCount; 239e9297d28Sopenharmony_ci} 240e9297d28Sopenharmony_ci 241e9297d28Sopenharmony_ciint RefCounter::GetStrongRefCount() 242e9297d28Sopenharmony_ci{ 243e9297d28Sopenharmony_ci return atomicStrong_.load(std::memory_order_relaxed); 244e9297d28Sopenharmony_ci} 245e9297d28Sopenharmony_ci 246e9297d28Sopenharmony_ciint RefCounter::IncWeakRefCount(const void* objectId) 247e9297d28Sopenharmony_ci{ 248e9297d28Sopenharmony_ci#ifdef DEBUG_REFBASE 249e9297d28Sopenharmony_ci GetNewTrace(objectId); 250e9297d28Sopenharmony_ci#endif 251e9297d28Sopenharmony_ci return atomicWeak_.fetch_add(1, std::memory_order_relaxed); 252e9297d28Sopenharmony_ci} 253e9297d28Sopenharmony_ci 254e9297d28Sopenharmony_ciint RefCounter::DecWeakRefCount(const void* objectId) 255e9297d28Sopenharmony_ci{ 256e9297d28Sopenharmony_ci#ifdef DEBUG_REFBASE 257e9297d28Sopenharmony_ci GetNewTrace(objectId); 258e9297d28Sopenharmony_ci#endif 259e9297d28Sopenharmony_ci int curCount = GetWeakRefCount(); 260e9297d28Sopenharmony_ci if (curCount > 0) { 261e9297d28Sopenharmony_ci curCount = atomicWeak_.fetch_sub(1, std::memory_order_release); 262e9297d28Sopenharmony_ci } 263e9297d28Sopenharmony_ci 264e9297d28Sopenharmony_ci if (curCount != 1) { 265e9297d28Sopenharmony_ci return curCount; 266e9297d28Sopenharmony_ci } 267e9297d28Sopenharmony_ci 268e9297d28Sopenharmony_ci if (IsLifeTimeExtended() && GetStrongRefCount() == 0) { 269e9297d28Sopenharmony_ci if (callback_) { 270e9297d28Sopenharmony_ci callback_(); 271e9297d28Sopenharmony_ci } 272e9297d28Sopenharmony_ci } else { 273e9297d28Sopenharmony_ci // only weak ptr case: no strong reference, delete the object 274e9297d28Sopenharmony_ci if (GetStrongRefCount() == INITIAL_PRIMARY_VALUE) { 275e9297d28Sopenharmony_ci if (callback_) { 276e9297d28Sopenharmony_ci callback_(); 277e9297d28Sopenharmony_ci } 278e9297d28Sopenharmony_ci } else { 279e9297d28Sopenharmony_ci // free RefCounter 280e9297d28Sopenharmony_ci DecRefCount(); 281e9297d28Sopenharmony_ci } 282e9297d28Sopenharmony_ci } 283e9297d28Sopenharmony_ci 284e9297d28Sopenharmony_ci return curCount; 285e9297d28Sopenharmony_ci} 286e9297d28Sopenharmony_ci 287e9297d28Sopenharmony_ciint RefCounter::GetWeakRefCount() 288e9297d28Sopenharmony_ci{ 289e9297d28Sopenharmony_ci return atomicWeak_.load(std::memory_order_relaxed); 290e9297d28Sopenharmony_ci} 291e9297d28Sopenharmony_ci 292e9297d28Sopenharmony_civoid RefCounter::SetAttemptAcquire() 293e9297d28Sopenharmony_ci{ 294e9297d28Sopenharmony_ci (void)atomicAttempt_.fetch_add(1, std::memory_order_relaxed); 295e9297d28Sopenharmony_ci} 296e9297d28Sopenharmony_ci 297e9297d28Sopenharmony_cibool RefCounter::IsAttemptAcquireSet() 298e9297d28Sopenharmony_ci{ 299e9297d28Sopenharmony_ci return static_cast<bool>(atomicAttempt_.load(std::memory_order_relaxed) > 0); 300e9297d28Sopenharmony_ci} 301e9297d28Sopenharmony_ci 302e9297d28Sopenharmony_civoid RefCounter::ClearAttemptAcquire() 303e9297d28Sopenharmony_ci{ 304e9297d28Sopenharmony_ci atomicAttempt_.fetch_sub(1, std::memory_order_relaxed); 305e9297d28Sopenharmony_ci} 306e9297d28Sopenharmony_ci 307e9297d28Sopenharmony_civoid RefCounter::ExtendObjectLifetime() 308e9297d28Sopenharmony_ci{ 309e9297d28Sopenharmony_ci atomicFlags_.fetch_or(FLAG_EXTEND_LIFE_TIME, std::memory_order_relaxed); 310e9297d28Sopenharmony_ci} 311e9297d28Sopenharmony_ci 312e9297d28Sopenharmony_cibool RefCounter::IsLifeTimeExtended() 313e9297d28Sopenharmony_ci{ 314e9297d28Sopenharmony_ci return static_cast<bool>(atomicFlags_.load(std::memory_order_relaxed) & FLAG_EXTEND_LIFE_TIME); 315e9297d28Sopenharmony_ci} 316e9297d28Sopenharmony_ci 317e9297d28Sopenharmony_cibool RefCounter::AttemptIncStrongRef(const void *objectId, int &outCount) 318e9297d28Sopenharmony_ci{ 319e9297d28Sopenharmony_ci int curCount = GetStrongRefCount(); 320e9297d28Sopenharmony_ci IncWeakRefCount(objectId); 321e9297d28Sopenharmony_ci 322e9297d28Sopenharmony_ci // if the object already had strong references.just promoting it. 323e9297d28Sopenharmony_ci while ((curCount > 0) && (curCount != INITIAL_PRIMARY_VALUE)) { 324e9297d28Sopenharmony_ci if (atomicStrong_.compare_exchange_weak(curCount, curCount + 1, std::memory_order_relaxed)) { 325e9297d28Sopenharmony_ci goto ATTEMPT_SUCCESS; 326e9297d28Sopenharmony_ci } 327e9297d28Sopenharmony_ci // someone else changed the counter.re-acquire the counter value. 328e9297d28Sopenharmony_ci curCount = atomicStrong_.load(std::memory_order_relaxed); 329e9297d28Sopenharmony_ci } 330e9297d28Sopenharmony_ci 331e9297d28Sopenharmony_ci if ((curCount == INITIAL_PRIMARY_VALUE) && !IsLifeTimeExtended()) { 332e9297d28Sopenharmony_ci // this object has a "normal" life-time, 333e9297d28Sopenharmony_ci while (curCount > 0) { 334e9297d28Sopenharmony_ci if (atomicStrong_.compare_exchange_weak(curCount, curCount + 1, std::memory_order_relaxed)) { 335e9297d28Sopenharmony_ci goto ATTEMPT_SUCCESS; 336e9297d28Sopenharmony_ci } 337e9297d28Sopenharmony_ci curCount = atomicStrong_.load(std::memory_order_relaxed); 338e9297d28Sopenharmony_ci } 339e9297d28Sopenharmony_ci } 340e9297d28Sopenharmony_ci 341e9297d28Sopenharmony_ci if (IsLifeTimeExtended()) { 342e9297d28Sopenharmony_ci curCount = atomicStrong_.fetch_add(1, std::memory_order_relaxed); 343e9297d28Sopenharmony_ci } 344e9297d28Sopenharmony_ci 345e9297d28Sopenharmony_ciATTEMPT_SUCCESS: 346e9297d28Sopenharmony_ci if (curCount >= INITIAL_PRIMARY_VALUE) { 347e9297d28Sopenharmony_ci outCount = curCount; 348e9297d28Sopenharmony_ci atomicStrong_.fetch_sub(INITIAL_PRIMARY_VALUE, std::memory_order_release); 349e9297d28Sopenharmony_ci return true; 350e9297d28Sopenharmony_ci } 351e9297d28Sopenharmony_ci 352e9297d28Sopenharmony_ci if (curCount < 0 || (!IsLifeTimeExtended() && curCount == 0)) { 353e9297d28Sopenharmony_ci // the object destroyed on strong reference count reduce to zero. 354e9297d28Sopenharmony_ci DecWeakRefCount(objectId); 355e9297d28Sopenharmony_ci return false; 356e9297d28Sopenharmony_ci } 357e9297d28Sopenharmony_ci 358e9297d28Sopenharmony_ci return true; 359e9297d28Sopenharmony_ci} 360e9297d28Sopenharmony_ci 361e9297d28Sopenharmony_cibool RefCounter::AttemptIncStrong(const void *objectId) 362e9297d28Sopenharmony_ci{ 363e9297d28Sopenharmony_ci IncWeakRefCount(objectId); 364e9297d28Sopenharmony_ci int curCount = GetStrongRefCount(); 365e9297d28Sopenharmony_ci while (curCount > 0) { 366e9297d28Sopenharmony_ci if (atomicStrong_.compare_exchange_weak(curCount, curCount + 1, std::memory_order_relaxed)) { 367e9297d28Sopenharmony_ci break; 368e9297d28Sopenharmony_ci } 369e9297d28Sopenharmony_ci // curCount has been updated. 370e9297d28Sopenharmony_ci } 371e9297d28Sopenharmony_ci if (curCount <= 0) { 372e9297d28Sopenharmony_ci DecWeakRefCount(objectId); 373e9297d28Sopenharmony_ci } 374e9297d28Sopenharmony_ci return curCount > 0; 375e9297d28Sopenharmony_ci} 376e9297d28Sopenharmony_ci 377e9297d28Sopenharmony_ciRefBase::RefBase() : refs_(new RefCounter()) 378e9297d28Sopenharmony_ci{ 379e9297d28Sopenharmony_ci refs_->IncRefCount(); 380e9297d28Sopenharmony_ci refs_->SetCallback(std::bind(&RefBase::RefPtrCallback, this)); 381e9297d28Sopenharmony_ci} 382e9297d28Sopenharmony_ci 383e9297d28Sopenharmony_ciRefBase::RefBase(const RefBase &) 384e9297d28Sopenharmony_ci{ 385e9297d28Sopenharmony_ci refs_ = new (std::nothrow) RefCounter(); 386e9297d28Sopenharmony_ci if (refs_ != nullptr) { 387e9297d28Sopenharmony_ci refs_->IncRefCount(); 388e9297d28Sopenharmony_ci refs_->SetCallback(std::bind(&RefBase::RefPtrCallback, this)); 389e9297d28Sopenharmony_ci } 390e9297d28Sopenharmony_ci} 391e9297d28Sopenharmony_ci 392e9297d28Sopenharmony_civoid RefBase::RefPtrCallback() 393e9297d28Sopenharmony_ci{ 394e9297d28Sopenharmony_ci delete this; 395e9297d28Sopenharmony_ci} 396e9297d28Sopenharmony_ci 397e9297d28Sopenharmony_ci/* 398e9297d28Sopenharmony_ci * The two ends of the assignment are two independent and exclusive, 399e9297d28Sopenharmony_ci * and the application should not share the reference counter. 400e9297d28Sopenharmony_ci * RISK: If there is a reference count on the left of the equal sign, 401e9297d28Sopenharmony_ci * it may cause a reference count exception 402e9297d28Sopenharmony_ci */ 403e9297d28Sopenharmony_ciRefBase &RefBase::operator=(const RefBase &) 404e9297d28Sopenharmony_ci{ 405e9297d28Sopenharmony_ci if (refs_ != nullptr) { 406e9297d28Sopenharmony_ci refs_->RemoveCallback(); 407e9297d28Sopenharmony_ci refs_->DecRefCount(); 408e9297d28Sopenharmony_ci } 409e9297d28Sopenharmony_ci 410e9297d28Sopenharmony_ci refs_ = new (std::nothrow) RefCounter(); 411e9297d28Sopenharmony_ci if (refs_ != nullptr) { 412e9297d28Sopenharmony_ci refs_->IncRefCount(); 413e9297d28Sopenharmony_ci refs_->SetCallback(std::bind(&RefBase::RefPtrCallback, this)); 414e9297d28Sopenharmony_ci } 415e9297d28Sopenharmony_ci 416e9297d28Sopenharmony_ci return *this; 417e9297d28Sopenharmony_ci} 418e9297d28Sopenharmony_ci 419e9297d28Sopenharmony_ciRefBase::RefBase(RefBase &&other) noexcept 420e9297d28Sopenharmony_ci{ 421e9297d28Sopenharmony_ci refs_ = other.refs_; 422e9297d28Sopenharmony_ci other.refs_ = nullptr; 423e9297d28Sopenharmony_ci} 424e9297d28Sopenharmony_ci 425e9297d28Sopenharmony_ciRefBase &RefBase::operator=(RefBase &&other) noexcept 426e9297d28Sopenharmony_ci{ 427e9297d28Sopenharmony_ci if (refs_ == other.refs_) { 428e9297d28Sopenharmony_ci return *this; 429e9297d28Sopenharmony_ci } 430e9297d28Sopenharmony_ci 431e9297d28Sopenharmony_ci if (refs_ != nullptr) { 432e9297d28Sopenharmony_ci refs_->RemoveCallback(); 433e9297d28Sopenharmony_ci refs_->DecRefCount(); 434e9297d28Sopenharmony_ci } 435e9297d28Sopenharmony_ci 436e9297d28Sopenharmony_ci refs_ = other.refs_; 437e9297d28Sopenharmony_ci other.refs_ = nullptr; 438e9297d28Sopenharmony_ci return *this; 439e9297d28Sopenharmony_ci} 440e9297d28Sopenharmony_ci 441e9297d28Sopenharmony_ciRefBase::~RefBase() 442e9297d28Sopenharmony_ci{ 443e9297d28Sopenharmony_ci if (refs_ != nullptr) { 444e9297d28Sopenharmony_ci refs_->RemoveCallback(); 445e9297d28Sopenharmony_ci if ((refs_->IsLifeTimeExtended() && refs_->GetWeakRefCount() == 0) || 446e9297d28Sopenharmony_ci refs_->GetStrongRefCount() == INITIAL_PRIMARY_VALUE) { 447e9297d28Sopenharmony_ci refs_->DecRefCount(); 448e9297d28Sopenharmony_ci } 449e9297d28Sopenharmony_ci refs_ = nullptr; 450e9297d28Sopenharmony_ci } 451e9297d28Sopenharmony_ci} 452e9297d28Sopenharmony_ci 453e9297d28Sopenharmony_civoid RefBase::ExtendObjectLifetime() 454e9297d28Sopenharmony_ci{ 455e9297d28Sopenharmony_ci refs_->ExtendObjectLifetime(); 456e9297d28Sopenharmony_ci} 457e9297d28Sopenharmony_ci 458e9297d28Sopenharmony_civoid RefBase::IncStrongRef(const void *objectId) 459e9297d28Sopenharmony_ci{ 460e9297d28Sopenharmony_ci if (refs_ == nullptr) { 461e9297d28Sopenharmony_ci return; 462e9297d28Sopenharmony_ci } 463e9297d28Sopenharmony_ci 464e9297d28Sopenharmony_ci IncWeakRef(objectId); 465e9297d28Sopenharmony_ci const int curCount = refs_->IncStrongRefCount(objectId); 466e9297d28Sopenharmony_ci if (curCount == INITIAL_PRIMARY_VALUE) { 467e9297d28Sopenharmony_ci OnFirstStrongRef(objectId); 468e9297d28Sopenharmony_ci } 469e9297d28Sopenharmony_ci if (refs_->IsAttemptAcquireSet()) { 470e9297d28Sopenharmony_ci refs_->ClearAttemptAcquire(); 471e9297d28Sopenharmony_ci refs_->DecStrongRefCount(objectId); 472e9297d28Sopenharmony_ci refs_->DecWeakRefCount(objectId); 473e9297d28Sopenharmony_ci } 474e9297d28Sopenharmony_ci} 475e9297d28Sopenharmony_ci 476e9297d28Sopenharmony_civoid RefBase::DecStrongRef(const void *objectId) 477e9297d28Sopenharmony_ci{ 478e9297d28Sopenharmony_ci if (refs_ == nullptr) { 479e9297d28Sopenharmony_ci return; 480e9297d28Sopenharmony_ci } 481e9297d28Sopenharmony_ci 482e9297d28Sopenharmony_ci RefCounter * const refs = refs_; 483e9297d28Sopenharmony_ci const int curCount = refs->DecStrongRefCount(objectId); 484e9297d28Sopenharmony_ci if (curCount == 1) { 485e9297d28Sopenharmony_ci OnLastStrongRef(objectId); 486e9297d28Sopenharmony_ci if (!refs->IsLifeTimeExtended()) { 487e9297d28Sopenharmony_ci if (refs->callback_) { 488e9297d28Sopenharmony_ci refs->callback_(); 489e9297d28Sopenharmony_ci } 490e9297d28Sopenharmony_ci } 491e9297d28Sopenharmony_ci } 492e9297d28Sopenharmony_ci 493e9297d28Sopenharmony_ci refs->DecWeakRefCount(objectId); 494e9297d28Sopenharmony_ci} 495e9297d28Sopenharmony_ci 496e9297d28Sopenharmony_ciint RefBase::GetSptrRefCount() 497e9297d28Sopenharmony_ci{ 498e9297d28Sopenharmony_ci if (refs_ == nullptr) { 499e9297d28Sopenharmony_ci return 0; 500e9297d28Sopenharmony_ci } 501e9297d28Sopenharmony_ci return refs_->GetStrongRefCount(); 502e9297d28Sopenharmony_ci} 503e9297d28Sopenharmony_ci 504e9297d28Sopenharmony_ciWeakRefCounter *RefBase::CreateWeakRef(void *cookie) 505e9297d28Sopenharmony_ci{ 506e9297d28Sopenharmony_ci if (refs_ != nullptr) { 507e9297d28Sopenharmony_ci return new WeakRefCounter(refs_, cookie); 508e9297d28Sopenharmony_ci } 509e9297d28Sopenharmony_ci return nullptr; 510e9297d28Sopenharmony_ci} 511e9297d28Sopenharmony_ci 512e9297d28Sopenharmony_civoid RefBase::IncWeakRef(const void *objectId) 513e9297d28Sopenharmony_ci{ 514e9297d28Sopenharmony_ci if (refs_ != nullptr) { 515e9297d28Sopenharmony_ci refs_->IncWeakRefCount(objectId); 516e9297d28Sopenharmony_ci } 517e9297d28Sopenharmony_ci} 518e9297d28Sopenharmony_ci 519e9297d28Sopenharmony_ciRefCounter *RefBase::GetRefCounter() const 520e9297d28Sopenharmony_ci{ 521e9297d28Sopenharmony_ci return refs_; 522e9297d28Sopenharmony_ci} 523e9297d28Sopenharmony_ci 524e9297d28Sopenharmony_civoid RefBase::DecWeakRef(const void *objectId) 525e9297d28Sopenharmony_ci{ 526e9297d28Sopenharmony_ci if (refs_ != nullptr) { 527e9297d28Sopenharmony_ci refs_->DecWeakRefCount(objectId); 528e9297d28Sopenharmony_ci } 529e9297d28Sopenharmony_ci} 530e9297d28Sopenharmony_ci 531e9297d28Sopenharmony_ciint RefBase::GetWptrRefCount() 532e9297d28Sopenharmony_ci{ 533e9297d28Sopenharmony_ci if (refs_ == nullptr) { 534e9297d28Sopenharmony_ci return 0; 535e9297d28Sopenharmony_ci } 536e9297d28Sopenharmony_ci return refs_->GetWeakRefCount(); 537e9297d28Sopenharmony_ci} 538e9297d28Sopenharmony_ci 539e9297d28Sopenharmony_cibool RefBase::AttemptAcquire(const void *objectId) 540e9297d28Sopenharmony_ci{ 541e9297d28Sopenharmony_ci if (refs_ == nullptr) { 542e9297d28Sopenharmony_ci return false; 543e9297d28Sopenharmony_ci } 544e9297d28Sopenharmony_ci 545e9297d28Sopenharmony_ci int count = 0; 546e9297d28Sopenharmony_ci if (refs_->AttemptIncStrongRef(objectId, count)) { 547e9297d28Sopenharmony_ci refs_->SetAttemptAcquire(); 548e9297d28Sopenharmony_ci if (count == INITIAL_PRIMARY_VALUE) { 549e9297d28Sopenharmony_ci OnFirstStrongRef(objectId); 550e9297d28Sopenharmony_ci } 551e9297d28Sopenharmony_ci 552e9297d28Sopenharmony_ci return true; 553e9297d28Sopenharmony_ci } 554e9297d28Sopenharmony_ci return false; 555e9297d28Sopenharmony_ci} 556e9297d28Sopenharmony_ci 557e9297d28Sopenharmony_cibool RefBase::AttemptIncStrongRef(const void *objectId) 558e9297d28Sopenharmony_ci{ 559e9297d28Sopenharmony_ci if ((refs_ != nullptr) && (OnAttemptPromoted(objectId))) { 560e9297d28Sopenharmony_ci int count = 0; 561e9297d28Sopenharmony_ci bool ret = refs_->AttemptIncStrongRef(objectId, count); 562e9297d28Sopenharmony_ci if (count == INITIAL_PRIMARY_VALUE) { 563e9297d28Sopenharmony_ci OnFirstStrongRef(objectId); 564e9297d28Sopenharmony_ci } 565e9297d28Sopenharmony_ci return ret; 566e9297d28Sopenharmony_ci } 567e9297d28Sopenharmony_ci 568e9297d28Sopenharmony_ci return false; 569e9297d28Sopenharmony_ci} 570e9297d28Sopenharmony_ci 571e9297d28Sopenharmony_cibool RefBase::AttemptIncStrong(const void *objectId) 572e9297d28Sopenharmony_ci{ 573e9297d28Sopenharmony_ci if (refs_ == nullptr) { 574e9297d28Sopenharmony_ci return false; 575e9297d28Sopenharmony_ci } 576e9297d28Sopenharmony_ci if (refs_->AttemptIncStrong(objectId)) { 577e9297d28Sopenharmony_ci refs_->SetAttemptAcquire(); 578e9297d28Sopenharmony_ci return true; 579e9297d28Sopenharmony_ci } 580e9297d28Sopenharmony_ci return false; 581e9297d28Sopenharmony_ci} 582e9297d28Sopenharmony_ci 583e9297d28Sopenharmony_cibool RefBase::IsAttemptAcquireSet() 584e9297d28Sopenharmony_ci{ 585e9297d28Sopenharmony_ci if (refs_ == nullptr) { 586e9297d28Sopenharmony_ci return false; 587e9297d28Sopenharmony_ci } 588e9297d28Sopenharmony_ci return refs_->IsAttemptAcquireSet(); 589e9297d28Sopenharmony_ci} 590e9297d28Sopenharmony_ci 591e9297d28Sopenharmony_cibool RefBase::IsExtendLifeTimeSet() 592e9297d28Sopenharmony_ci{ 593e9297d28Sopenharmony_ci if (refs_ == nullptr) { 594e9297d28Sopenharmony_ci return false; 595e9297d28Sopenharmony_ci } 596e9297d28Sopenharmony_ci return refs_->IsLifeTimeExtended(); 597e9297d28Sopenharmony_ci} 598e9297d28Sopenharmony_ci 599e9297d28Sopenharmony_civoid RefBase::OnFirstStrongRef(const void*) 600e9297d28Sopenharmony_ci{} 601e9297d28Sopenharmony_ci 602e9297d28Sopenharmony_civoid RefBase::OnLastStrongRef(const void*) 603e9297d28Sopenharmony_ci{} 604e9297d28Sopenharmony_ci 605e9297d28Sopenharmony_civoid RefBase::OnLastWeakRef(const void*) 606e9297d28Sopenharmony_ci{} 607e9297d28Sopenharmony_ci 608e9297d28Sopenharmony_cibool RefBase::OnAttemptPromoted(const void*) 609e9297d28Sopenharmony_ci{ 610e9297d28Sopenharmony_ci return true; 611e9297d28Sopenharmony_ci} 612e9297d28Sopenharmony_ci 613e9297d28Sopenharmony_ci} // namespace OHOS 614