13f4cbf05Sopenharmony_ci/* 23f4cbf05Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 33f4cbf05Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43f4cbf05Sopenharmony_ci * you may not use this file except in compliance with the License. 53f4cbf05Sopenharmony_ci * You may obtain a copy of the License at 63f4cbf05Sopenharmony_ci * 73f4cbf05Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 83f4cbf05Sopenharmony_ci * 93f4cbf05Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103f4cbf05Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113f4cbf05Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123f4cbf05Sopenharmony_ci * See the License for the specific language governing permissions and 133f4cbf05Sopenharmony_ci * limitations under the License. 143f4cbf05Sopenharmony_ci */ 153f4cbf05Sopenharmony_ci 163f4cbf05Sopenharmony_ci#include "refbase.h" 173f4cbf05Sopenharmony_ci#include "utils_log.h" 183f4cbf05Sopenharmony_ci#ifdef DEBUG_REFBASE 193f4cbf05Sopenharmony_ci#include <unistd.h> 203f4cbf05Sopenharmony_ci#endif 213f4cbf05Sopenharmony_ci 223f4cbf05Sopenharmony_cinamespace OHOS { 233f4cbf05Sopenharmony_ci 243f4cbf05Sopenharmony_ciWeakRefCounter::WeakRefCounter(RefCounter *counter, void *cookie) 253f4cbf05Sopenharmony_ci : atomicWeak_(0), refCounter_(counter), cookie_(cookie) 263f4cbf05Sopenharmony_ci{ 273f4cbf05Sopenharmony_ci if (refCounter_ != nullptr) { 283f4cbf05Sopenharmony_ci refCounter_->IncRefCount(); 293f4cbf05Sopenharmony_ci } 303f4cbf05Sopenharmony_ci} 313f4cbf05Sopenharmony_ci 323f4cbf05Sopenharmony_ciWeakRefCounter::~WeakRefCounter() 333f4cbf05Sopenharmony_ci{ 343f4cbf05Sopenharmony_ci if (refCounter_ != nullptr) { 353f4cbf05Sopenharmony_ci refCounter_->DecRefCount(); 363f4cbf05Sopenharmony_ci } 373f4cbf05Sopenharmony_ci} 383f4cbf05Sopenharmony_ci 393f4cbf05Sopenharmony_ciint WeakRefCounter::GetWeakRefCount() const 403f4cbf05Sopenharmony_ci{ 413f4cbf05Sopenharmony_ci return atomicWeak_.load(std::memory_order_relaxed); 423f4cbf05Sopenharmony_ci} 433f4cbf05Sopenharmony_ci 443f4cbf05Sopenharmony_civoid* WeakRefCounter::GetRefPtr() 453f4cbf05Sopenharmony_ci{ 463f4cbf05Sopenharmony_ci if ((cookie_ != nullptr) && (!refCounter_->IsRefPtrValid())) { 473f4cbf05Sopenharmony_ci cookie_ = nullptr; 483f4cbf05Sopenharmony_ci } 493f4cbf05Sopenharmony_ci return cookie_; 503f4cbf05Sopenharmony_ci} 513f4cbf05Sopenharmony_ci 523f4cbf05Sopenharmony_civoid WeakRefCounter::IncWeakRefCount(const void *objectId) 533f4cbf05Sopenharmony_ci{ 543f4cbf05Sopenharmony_ci if (atomicWeak_.fetch_add(1, std::memory_order_relaxed) == 0) { 553f4cbf05Sopenharmony_ci refCounter_->IncWeakRefCount(objectId); 563f4cbf05Sopenharmony_ci } 573f4cbf05Sopenharmony_ci} 583f4cbf05Sopenharmony_ci 593f4cbf05Sopenharmony_civoid WeakRefCounter::DecWeakRefCount(const void *objectId) 603f4cbf05Sopenharmony_ci{ 613f4cbf05Sopenharmony_ci if (atomicWeak_.fetch_sub(1, std::memory_order_release) == 1) { 623f4cbf05Sopenharmony_ci refCounter_->DecWeakRefCount(objectId); 633f4cbf05Sopenharmony_ci delete this; 643f4cbf05Sopenharmony_ci } 653f4cbf05Sopenharmony_ci} 663f4cbf05Sopenharmony_ci 673f4cbf05Sopenharmony_cibool WeakRefCounter::AttemptIncStrongRef(const void *objectId) 683f4cbf05Sopenharmony_ci{ 693f4cbf05Sopenharmony_ci int unuse = 0; 703f4cbf05Sopenharmony_ci return refCounter_->AttemptIncStrongRef(objectId, unuse); 713f4cbf05Sopenharmony_ci} 723f4cbf05Sopenharmony_ci 733f4cbf05Sopenharmony_ci#if ((defined DEBUG_REFBASE) && (!defined PRINT_TRACK_AT_ONCE)) 743f4cbf05Sopenharmony_ci// RefTracker is a debug tool, used to record the trace of RefBase. 753f4cbf05Sopenharmony_ci// RefTracker will save the information about the count of RefBase, 763f4cbf05Sopenharmony_ci// including the pointer of sptr/wptr(The pointer of itself, not the pointer 773f4cbf05Sopenharmony_ci// it manages), the amount of strong/weak/refcout and the PID&TID. 783f4cbf05Sopenharmony_ci// The Tracker can live with RefCounter. 793f4cbf05Sopenharmony_ci// User should keep thread-safety of RefTracker. 803f4cbf05Sopenharmony_ciclass RefTracker { 813f4cbf05Sopenharmony_cipublic: 823f4cbf05Sopenharmony_ci RefTracker(RefTracker* exTracker, const void* id, int strong, int weak, int ref, int pid, int tid); 833f4cbf05Sopenharmony_ci 843f4cbf05Sopenharmony_ci void PrintTrace(const void* refCounterPtr); 853f4cbf05Sopenharmony_ci 863f4cbf05Sopenharmony_ci RefTracker* PopTrace(const void* refCounterPtr); 873f4cbf05Sopenharmony_ci 883f4cbf05Sopenharmony_ciprivate: 893f4cbf05Sopenharmony_ci const void* ptrID; 903f4cbf05Sopenharmony_ci int strongRefCnt; 913f4cbf05Sopenharmony_ci int weakRefCnt; 923f4cbf05Sopenharmony_ci int refCnt; 933f4cbf05Sopenharmony_ci int PID; 943f4cbf05Sopenharmony_ci int TID; 953f4cbf05Sopenharmony_ci RefTracker* exTrace; 963f4cbf05Sopenharmony_ci}; 973f4cbf05Sopenharmony_ci 983f4cbf05Sopenharmony_ciRefTracker::RefTracker(RefTracker* exTracker, const void* id, int strong, int weak, int ref, int pid, int tid) 993f4cbf05Sopenharmony_ci : ptrID (id), strongRefCnt (strong), weakRefCnt (weak), refCnt (ref), PID (pid), TID (tid), exTrace (exTracker) 1003f4cbf05Sopenharmony_ci{ 1013f4cbf05Sopenharmony_ci} 1023f4cbf05Sopenharmony_ci 1033f4cbf05Sopenharmony_civoid RefTracker::PrintTrace(const void* refCounterPtr) 1043f4cbf05Sopenharmony_ci{ 1053f4cbf05Sopenharmony_ci UTILS_LOGI("%{public}p call %{public}p. strong: %{public}d weak: %{public}d " \ 1063f4cbf05Sopenharmony_ci "refcnt: %{public}d PID: %{public}d TID: %{public}d", 1073f4cbf05Sopenharmony_ci ptrID, refCounterPtr, strongRefCnt, weakRefCnt, refCnt, PID, TID); 1083f4cbf05Sopenharmony_ci} 1093f4cbf05Sopenharmony_ci 1103f4cbf05Sopenharmony_ciRefTracker* RefTracker::PopTrace(const void* refCounterPtr) 1113f4cbf05Sopenharmony_ci{ 1123f4cbf05Sopenharmony_ci RefTracker* ref = exTrace; 1133f4cbf05Sopenharmony_ci PrintTrace(refCounterPtr); 1143f4cbf05Sopenharmony_ci delete this; 1153f4cbf05Sopenharmony_ci return ref; 1163f4cbf05Sopenharmony_ci} 1173f4cbf05Sopenharmony_ci#endif 1183f4cbf05Sopenharmony_ci 1193f4cbf05Sopenharmony_ci#ifdef DEBUG_REFBASE 1203f4cbf05Sopenharmony_ci#ifdef PRINT_TRACK_AT_ONCE 1213f4cbf05Sopenharmony_civoid RefCounter::PrintRefs(const void* objectId) 1223f4cbf05Sopenharmony_ci{ 1233f4cbf05Sopenharmony_ci std::lock_guard<std::mutex> lock(trackerMutex); 1243f4cbf05Sopenharmony_ci UTILS_LOGI("%{public}p call %{public}p. strong: %{public}d weak: %{public}d " \ 1253f4cbf05Sopenharmony_ci "refcnt: %{public}d", objectId, this, atomicStrong_.load(std::memory_order_relaxed), 1263f4cbf05Sopenharmony_ci atomicWeak_.load(std::memory_order_relaxed), atomicRefCount_.load(std::memory_order_relaxed)); 1273f4cbf05Sopenharmony_ci} 1283f4cbf05Sopenharmony_ci#else 1293f4cbf05Sopenharmony_civoid RefCounter::GetNewTrace(const void* objectId) 1303f4cbf05Sopenharmony_ci{ 1313f4cbf05Sopenharmony_ci std::lock_guard<std::mutex> lock(trackerMutex); 1323f4cbf05Sopenharmony_ci RefTracker* newTracker = new RefTracker(refTracker, objectId, atomicStrong_, 1333f4cbf05Sopenharmony_ci atomicWeak_, atomicRefCount_, getpid(), gettid()); 1343f4cbf05Sopenharmony_ci refTracker = newTracker; 1353f4cbf05Sopenharmony_ci} 1363f4cbf05Sopenharmony_ci 1373f4cbf05Sopenharmony_civoid RefCounter::PrintTracker() 1383f4cbf05Sopenharmony_ci{ 1393f4cbf05Sopenharmony_ci std::lock_guard<std::mutex> lock(trackerMutex); 1403f4cbf05Sopenharmony_ci if (refTracker) { 1413f4cbf05Sopenharmony_ci UTILS_LOGI("%{public}p start backtrace", this); 1423f4cbf05Sopenharmony_ci while (refTracker) { 1433f4cbf05Sopenharmony_ci refTracker = refTracker->PopTrace(this); 1443f4cbf05Sopenharmony_ci } 1453f4cbf05Sopenharmony_ci UTILS_LOGI("%{public}p end backtrace", this); 1463f4cbf05Sopenharmony_ci } 1473f4cbf05Sopenharmony_ci} 1483f4cbf05Sopenharmony_ci#endif 1493f4cbf05Sopenharmony_ci 1503f4cbf05Sopenharmony_ci#ifndef TRACK_ALL 1513f4cbf05Sopenharmony_civoid RefCounter::EnableTracker() 1523f4cbf05Sopenharmony_ci{ 1533f4cbf05Sopenharmony_ci std::lock_guard<std::mutex> lock(trackerMutex); 1543f4cbf05Sopenharmony_ci#ifdef PRINT_TRACK_AT_ONCE 1553f4cbf05Sopenharmony_ci UTILS_LOGI("%{public}p start tracking", this); 1563f4cbf05Sopenharmony_ci#endif 1573f4cbf05Sopenharmony_ci enableTrack = true; 1583f4cbf05Sopenharmony_ci} 1593f4cbf05Sopenharmony_ci#endif 1603f4cbf05Sopenharmony_ci#endif 1613f4cbf05Sopenharmony_ci 1623f4cbf05Sopenharmony_civoid RefCounter::DebugRefBase([[maybe_unused]]const void* objectId) 1633f4cbf05Sopenharmony_ci{ 1643f4cbf05Sopenharmony_ci#ifdef DEBUG_REFBASE 1653f4cbf05Sopenharmony_ci if (enableTrack) { 1663f4cbf05Sopenharmony_ci#ifdef PRINT_TRACK_AT_ONCE 1673f4cbf05Sopenharmony_ci PrintRefs(objectId); 1683f4cbf05Sopenharmony_ci#else 1693f4cbf05Sopenharmony_ci GetNewTrace(objectId); 1703f4cbf05Sopenharmony_ci#endif 1713f4cbf05Sopenharmony_ci } 1723f4cbf05Sopenharmony_ci#endif 1733f4cbf05Sopenharmony_ci} 1743f4cbf05Sopenharmony_ci 1753f4cbf05Sopenharmony_ciRefCounter::RefCounter() 1763f4cbf05Sopenharmony_ci : atomicStrong_(INITIAL_PRIMARY_VALUE), atomicWeak_(0), atomicRefCount_(0), atomicFlags_(0), atomicAttempt_(0) 1773f4cbf05Sopenharmony_ci{ 1783f4cbf05Sopenharmony_ci} 1793f4cbf05Sopenharmony_ci 1803f4cbf05Sopenharmony_ciint RefCounter::GetRefCount() 1813f4cbf05Sopenharmony_ci{ 1823f4cbf05Sopenharmony_ci return atomicRefCount_.load(std::memory_order_relaxed); 1833f4cbf05Sopenharmony_ci} 1843f4cbf05Sopenharmony_ci 1853f4cbf05Sopenharmony_civoid RefCounter::IncRefCount() 1863f4cbf05Sopenharmony_ci{ 1873f4cbf05Sopenharmony_ci atomicRefCount_.fetch_add(1, std::memory_order_relaxed); 1883f4cbf05Sopenharmony_ci} 1893f4cbf05Sopenharmony_ci 1903f4cbf05Sopenharmony_civoid RefCounter::DecRefCount() 1913f4cbf05Sopenharmony_ci{ 1923f4cbf05Sopenharmony_ci if (atomicRefCount_.load(std::memory_order_relaxed) > 0) { 1933f4cbf05Sopenharmony_ci if (atomicRefCount_.fetch_sub(1, std::memory_order_release) == 1) { 1943f4cbf05Sopenharmony_ci delete (this); 1953f4cbf05Sopenharmony_ci } 1963f4cbf05Sopenharmony_ci } 1973f4cbf05Sopenharmony_ci} 1983f4cbf05Sopenharmony_ci 1993f4cbf05Sopenharmony_civoid RefCounter::SetCallback(const RefPtrCallback& callback) 2003f4cbf05Sopenharmony_ci{ 2013f4cbf05Sopenharmony_ci callback_ = callback; 2023f4cbf05Sopenharmony_ci} 2033f4cbf05Sopenharmony_ci 2043f4cbf05Sopenharmony_civoid RefCounter::RemoveCallback() 2053f4cbf05Sopenharmony_ci{ 2063f4cbf05Sopenharmony_ci callback_ = nullptr; 2073f4cbf05Sopenharmony_ci} 2083f4cbf05Sopenharmony_ci 2093f4cbf05Sopenharmony_cibool RefCounter::IsRefPtrValid() 2103f4cbf05Sopenharmony_ci{ 2113f4cbf05Sopenharmony_ci return callback_ != nullptr; 2123f4cbf05Sopenharmony_ci} 2133f4cbf05Sopenharmony_ci 2143f4cbf05Sopenharmony_ci#ifndef EMULATOR_PLATFORM 2153f4cbf05Sopenharmony_civoid RefCounter::SetCanPromote(const CanPromote &canPromote) 2163f4cbf05Sopenharmony_ci{ 2173f4cbf05Sopenharmony_ci canPromote_ = canPromote; 2183f4cbf05Sopenharmony_ci} 2193f4cbf05Sopenharmony_ci 2203f4cbf05Sopenharmony_civoid RefCounter::RemoveCanPromote() 2213f4cbf05Sopenharmony_ci{ 2223f4cbf05Sopenharmony_ci canPromote_ = nullptr; 2233f4cbf05Sopenharmony_ci} 2243f4cbf05Sopenharmony_ci 2253f4cbf05Sopenharmony_cibool RefCounter::IsCanPromoteValid() 2263f4cbf05Sopenharmony_ci{ 2273f4cbf05Sopenharmony_ci return canPromote_ != nullptr; 2283f4cbf05Sopenharmony_ci} 2293f4cbf05Sopenharmony_ci#endif 2303f4cbf05Sopenharmony_ci 2313f4cbf05Sopenharmony_ciRefCounter::~RefCounter() 2323f4cbf05Sopenharmony_ci{ 2333f4cbf05Sopenharmony_ci#ifdef DEBUG_REFBASE 2343f4cbf05Sopenharmony_ci if (enableTrack) { 2353f4cbf05Sopenharmony_ci#ifdef PRINT_TRACK_AT_ONCE 2363f4cbf05Sopenharmony_ci UTILS_LOGI("%{public}p end tracking", this); 2373f4cbf05Sopenharmony_ci#else 2383f4cbf05Sopenharmony_ci PrintTracker(); 2393f4cbf05Sopenharmony_ci#endif 2403f4cbf05Sopenharmony_ci } 2413f4cbf05Sopenharmony_ci#endif 2423f4cbf05Sopenharmony_ci} 2433f4cbf05Sopenharmony_ci 2443f4cbf05Sopenharmony_ciint RefCounter::IncStrongRefCount(const void* objectId) 2453f4cbf05Sopenharmony_ci{ 2463f4cbf05Sopenharmony_ci DebugRefBase(objectId); 2473f4cbf05Sopenharmony_ci int curCount = atomicStrong_.load(std::memory_order_relaxed); 2483f4cbf05Sopenharmony_ci if (curCount >= 0) { 2493f4cbf05Sopenharmony_ci curCount = atomicStrong_.fetch_add(1, std::memory_order_relaxed); 2503f4cbf05Sopenharmony_ci if (curCount == INITIAL_PRIMARY_VALUE) { 2513f4cbf05Sopenharmony_ci atomicStrong_.fetch_sub(INITIAL_PRIMARY_VALUE, std::memory_order_release); 2523f4cbf05Sopenharmony_ci } 2533f4cbf05Sopenharmony_ci } 2543f4cbf05Sopenharmony_ci 2553f4cbf05Sopenharmony_ci return curCount; 2563f4cbf05Sopenharmony_ci} 2573f4cbf05Sopenharmony_ci 2583f4cbf05Sopenharmony_ciint RefCounter::DecStrongRefCount(const void* objectId) 2593f4cbf05Sopenharmony_ci{ 2603f4cbf05Sopenharmony_ci DebugRefBase(objectId); 2613f4cbf05Sopenharmony_ci int curCount = GetStrongRefCount(); 2623f4cbf05Sopenharmony_ci if (curCount == INITIAL_PRIMARY_VALUE) { 2633f4cbf05Sopenharmony_ci // unexpected case: there had never a strong reference. 2643f4cbf05Sopenharmony_ci UTILS_LOGD("decStrongRef when there is nerver a strong reference"); 2653f4cbf05Sopenharmony_ci } else if (curCount > 0) { 2663f4cbf05Sopenharmony_ci // we should update the current count here. 2673f4cbf05Sopenharmony_ci // it may be changed after last operation. 2683f4cbf05Sopenharmony_ci curCount = atomicStrong_.fetch_sub(1, std::memory_order_release); 2693f4cbf05Sopenharmony_ci } 2703f4cbf05Sopenharmony_ci 2713f4cbf05Sopenharmony_ci return curCount; 2723f4cbf05Sopenharmony_ci} 2733f4cbf05Sopenharmony_ci 2743f4cbf05Sopenharmony_ciint RefCounter::GetStrongRefCount() 2753f4cbf05Sopenharmony_ci{ 2763f4cbf05Sopenharmony_ci return atomicStrong_.load(std::memory_order_relaxed); 2773f4cbf05Sopenharmony_ci} 2783f4cbf05Sopenharmony_ci 2793f4cbf05Sopenharmony_ciint RefCounter::IncWeakRefCount(const void* objectId) 2803f4cbf05Sopenharmony_ci{ 2813f4cbf05Sopenharmony_ci DebugRefBase(objectId); 2823f4cbf05Sopenharmony_ci return atomicWeak_.fetch_add(1, std::memory_order_relaxed); 2833f4cbf05Sopenharmony_ci} 2843f4cbf05Sopenharmony_ci 2853f4cbf05Sopenharmony_ciint RefCounter::DecWeakRefCount(const void* objectId) 2863f4cbf05Sopenharmony_ci{ 2873f4cbf05Sopenharmony_ci DebugRefBase(objectId); 2883f4cbf05Sopenharmony_ci int curCount = GetWeakRefCount(); 2893f4cbf05Sopenharmony_ci if (curCount > 0) { 2903f4cbf05Sopenharmony_ci curCount = atomicWeak_.fetch_sub(1, std::memory_order_release); 2913f4cbf05Sopenharmony_ci } 2923f4cbf05Sopenharmony_ci 2933f4cbf05Sopenharmony_ci if (curCount != 1) { 2943f4cbf05Sopenharmony_ci return curCount; 2953f4cbf05Sopenharmony_ci } 2963f4cbf05Sopenharmony_ci std::atomic_thread_fence(std::memory_order_acquire); 2973f4cbf05Sopenharmony_ci if (IsLifeTimeExtended()) { 2983f4cbf05Sopenharmony_ci if (callback_) { 2993f4cbf05Sopenharmony_ci callback_(); 3003f4cbf05Sopenharmony_ci } 3013f4cbf05Sopenharmony_ci } else { 3023f4cbf05Sopenharmony_ci // only weak ptr but never had a strong ref, we should do nothing here theoretically. But it may cause a leak. 3033f4cbf05Sopenharmony_ci if (GetStrongRefCount() == INITIAL_PRIMARY_VALUE) { 3043f4cbf05Sopenharmony_ci UTILS_LOGW("dec the last weakRef before it had a strong reference, delete refbase to avoid Memory Leak"); 3053f4cbf05Sopenharmony_ci if (callback_) { 3063f4cbf05Sopenharmony_ci callback_(); 3073f4cbf05Sopenharmony_ci } 3083f4cbf05Sopenharmony_ci } else { 3093f4cbf05Sopenharmony_ci // free RefCounter 3103f4cbf05Sopenharmony_ci DecRefCount(); 3113f4cbf05Sopenharmony_ci } 3123f4cbf05Sopenharmony_ci } 3133f4cbf05Sopenharmony_ci 3143f4cbf05Sopenharmony_ci return curCount; 3153f4cbf05Sopenharmony_ci} 3163f4cbf05Sopenharmony_ci 3173f4cbf05Sopenharmony_ciint RefCounter::GetWeakRefCount() 3183f4cbf05Sopenharmony_ci{ 3193f4cbf05Sopenharmony_ci return atomicWeak_.load(std::memory_order_relaxed); 3203f4cbf05Sopenharmony_ci} 3213f4cbf05Sopenharmony_ci 3223f4cbf05Sopenharmony_ciint RefCounter::GetAttemptAcquire() 3233f4cbf05Sopenharmony_ci{ 3243f4cbf05Sopenharmony_ci return atomicAttempt_.load(std::memory_order_relaxed); 3253f4cbf05Sopenharmony_ci} 3263f4cbf05Sopenharmony_ci 3273f4cbf05Sopenharmony_civoid RefCounter::SetAttemptAcquire() 3283f4cbf05Sopenharmony_ci{ 3293f4cbf05Sopenharmony_ci (void)atomicAttempt_.fetch_add(1, std::memory_order_relaxed); 3303f4cbf05Sopenharmony_ci} 3313f4cbf05Sopenharmony_ci 3323f4cbf05Sopenharmony_cibool RefCounter::IsAttemptAcquireSet() 3333f4cbf05Sopenharmony_ci{ 3343f4cbf05Sopenharmony_ci return static_cast<bool>(atomicAttempt_.load(std::memory_order_relaxed) > 0); 3353f4cbf05Sopenharmony_ci} 3363f4cbf05Sopenharmony_ci 3373f4cbf05Sopenharmony_civoid RefCounter::ClearAttemptAcquire() 3383f4cbf05Sopenharmony_ci{ 3393f4cbf05Sopenharmony_ci atomicAttempt_.fetch_sub(1, std::memory_order_relaxed); 3403f4cbf05Sopenharmony_ci} 3413f4cbf05Sopenharmony_ci 3423f4cbf05Sopenharmony_civoid RefCounter::ExtendObjectLifetime() 3433f4cbf05Sopenharmony_ci{ 3443f4cbf05Sopenharmony_ci atomicFlags_.fetch_or(FLAG_EXTEND_LIFE_TIME, std::memory_order_relaxed); 3453f4cbf05Sopenharmony_ci} 3463f4cbf05Sopenharmony_ci 3473f4cbf05Sopenharmony_cibool RefCounter::IsLifeTimeExtended() 3483f4cbf05Sopenharmony_ci{ 3493f4cbf05Sopenharmony_ci return static_cast<bool>(atomicFlags_.load(std::memory_order_relaxed) & FLAG_EXTEND_LIFE_TIME); 3503f4cbf05Sopenharmony_ci} 3513f4cbf05Sopenharmony_ci 3523f4cbf05Sopenharmony_cibool RefCounter::AttemptIncStrongRef(const void *objectId, int &outCount) 3533f4cbf05Sopenharmony_ci{ 3543f4cbf05Sopenharmony_ci int curCount = GetStrongRefCount(); 3553f4cbf05Sopenharmony_ci IncWeakRefCount(objectId); 3563f4cbf05Sopenharmony_ci 3573f4cbf05Sopenharmony_ci // if the object already had strong references.just promoting it. 3583f4cbf05Sopenharmony_ci while ((curCount > 0) && (curCount != INITIAL_PRIMARY_VALUE)) { 3593f4cbf05Sopenharmony_ci if (atomicStrong_.compare_exchange_weak(curCount, curCount + 1, std::memory_order_relaxed)) { 3603f4cbf05Sopenharmony_ci goto ATTEMPT_SUCCESS; 3613f4cbf05Sopenharmony_ci } 3623f4cbf05Sopenharmony_ci // someone else changed the counter.re-acquire the counter value. 3633f4cbf05Sopenharmony_ci curCount = atomicStrong_.load(std::memory_order_relaxed); 3643f4cbf05Sopenharmony_ci } 3653f4cbf05Sopenharmony_ci 3663f4cbf05Sopenharmony_ci if ((curCount == INITIAL_PRIMARY_VALUE) && !IsLifeTimeExtended()) { 3673f4cbf05Sopenharmony_ci // this object has a "normal" life-time, 3683f4cbf05Sopenharmony_ci while (curCount > 0) { 3693f4cbf05Sopenharmony_ci if (atomicStrong_.compare_exchange_weak(curCount, curCount + 1, std::memory_order_relaxed)) { 3703f4cbf05Sopenharmony_ci goto ATTEMPT_SUCCESS; 3713f4cbf05Sopenharmony_ci } 3723f4cbf05Sopenharmony_ci curCount = atomicStrong_.load(std::memory_order_relaxed); 3733f4cbf05Sopenharmony_ci } 3743f4cbf05Sopenharmony_ci } 3753f4cbf05Sopenharmony_ci 3763f4cbf05Sopenharmony_ci if (IsLifeTimeExtended()) { 3773f4cbf05Sopenharmony_ci#ifndef EMULATOR_PLATFORM 3783f4cbf05Sopenharmony_ci if (!IsCanPromoteValid() || !canPromote_()) { 3793f4cbf05Sopenharmony_ci return false; 3803f4cbf05Sopenharmony_ci } 3813f4cbf05Sopenharmony_ci#endif 3823f4cbf05Sopenharmony_ci curCount = atomicStrong_.fetch_add(1, std::memory_order_relaxed); 3833f4cbf05Sopenharmony_ci } 3843f4cbf05Sopenharmony_ci 3853f4cbf05Sopenharmony_ciATTEMPT_SUCCESS: 3863f4cbf05Sopenharmony_ci if (curCount == INITIAL_PRIMARY_VALUE) { 3873f4cbf05Sopenharmony_ci outCount = curCount; 3883f4cbf05Sopenharmony_ci atomicStrong_.fetch_sub(INITIAL_PRIMARY_VALUE, std::memory_order_release); 3893f4cbf05Sopenharmony_ci return true; 3903f4cbf05Sopenharmony_ci } 3913f4cbf05Sopenharmony_ci 3923f4cbf05Sopenharmony_ci if (curCount < 0 || (!IsLifeTimeExtended() && curCount == 0)) { 3933f4cbf05Sopenharmony_ci // the object destroyed on strong reference count reduce to zero. 3943f4cbf05Sopenharmony_ci DecWeakRefCount(objectId); 3953f4cbf05Sopenharmony_ci return false; 3963f4cbf05Sopenharmony_ci } 3973f4cbf05Sopenharmony_ci 3983f4cbf05Sopenharmony_ci return true; 3993f4cbf05Sopenharmony_ci} 4003f4cbf05Sopenharmony_ci 4013f4cbf05Sopenharmony_cibool RefCounter::AttemptIncStrong(const void *objectId) 4023f4cbf05Sopenharmony_ci{ 4033f4cbf05Sopenharmony_ci IncWeakRefCount(objectId); 4043f4cbf05Sopenharmony_ci int curCount = GetStrongRefCount(); 4053f4cbf05Sopenharmony_ci while (curCount > 0) { 4063f4cbf05Sopenharmony_ci if (atomicStrong_.compare_exchange_weak(curCount, curCount + 1, std::memory_order_relaxed)) { 4073f4cbf05Sopenharmony_ci break; 4083f4cbf05Sopenharmony_ci } 4093f4cbf05Sopenharmony_ci // curCount has been updated. 4103f4cbf05Sopenharmony_ci } 4113f4cbf05Sopenharmony_ci if (curCount <= 0) { 4123f4cbf05Sopenharmony_ci DecWeakRefCount(objectId); 4133f4cbf05Sopenharmony_ci } 4143f4cbf05Sopenharmony_ci return curCount > 0; 4153f4cbf05Sopenharmony_ci} 4163f4cbf05Sopenharmony_ci 4173f4cbf05Sopenharmony_ciRefBase::RefBase() : refs_(new RefCounter()) 4183f4cbf05Sopenharmony_ci{ 4193f4cbf05Sopenharmony_ci refs_->IncRefCount(); 4203f4cbf05Sopenharmony_ci refs_->SetCallback([this] { this->RefPtrCallback(); }); 4213f4cbf05Sopenharmony_ci#ifndef EMULATOR_PLATFORM 4223f4cbf05Sopenharmony_ci refs_->SetCanPromote([this] { return this->CanPromote(); }); 4233f4cbf05Sopenharmony_ci#endif 4243f4cbf05Sopenharmony_ci} 4253f4cbf05Sopenharmony_ci 4263f4cbf05Sopenharmony_ciRefBase::RefBase(const RefBase &) 4273f4cbf05Sopenharmony_ci{ 4283f4cbf05Sopenharmony_ci refs_ = new (std::nothrow) RefCounter(); 4293f4cbf05Sopenharmony_ci if (refs_ != nullptr) { 4303f4cbf05Sopenharmony_ci refs_->IncRefCount(); 4313f4cbf05Sopenharmony_ci refs_->SetCallback([this] { this->RefPtrCallback(); }); 4323f4cbf05Sopenharmony_ci#ifndef EMULATOR_PLATFORM 4333f4cbf05Sopenharmony_ci refs_->SetCanPromote([this] { return this->CanPromote(); }); 4343f4cbf05Sopenharmony_ci#endif 4353f4cbf05Sopenharmony_ci } 4363f4cbf05Sopenharmony_ci} 4373f4cbf05Sopenharmony_ci 4383f4cbf05Sopenharmony_ci#ifndef EMULATOR_PLATFORM 4393f4cbf05Sopenharmony_cibool RefBase::CanPromote() 4403f4cbf05Sopenharmony_ci{ 4413f4cbf05Sopenharmony_ci return true; 4423f4cbf05Sopenharmony_ci} 4433f4cbf05Sopenharmony_ci#endif 4443f4cbf05Sopenharmony_ci 4453f4cbf05Sopenharmony_civoid RefBase::RefPtrCallback() 4463f4cbf05Sopenharmony_ci{ 4473f4cbf05Sopenharmony_ci delete this; 4483f4cbf05Sopenharmony_ci} 4493f4cbf05Sopenharmony_ci 4503f4cbf05Sopenharmony_ci/* 4513f4cbf05Sopenharmony_ci * The two ends of the assignment are two independent and exclusive, 4523f4cbf05Sopenharmony_ci * and the application should not share the reference counter. 4533f4cbf05Sopenharmony_ci * RISK: If there is a reference count on the left of the equal sign, 4543f4cbf05Sopenharmony_ci * it may cause a reference count exception 4553f4cbf05Sopenharmony_ci */ 4563f4cbf05Sopenharmony_ciRefBase &RefBase::operator=(const RefBase &) 4573f4cbf05Sopenharmony_ci{ 4583f4cbf05Sopenharmony_ci if (refs_ != nullptr) { 4593f4cbf05Sopenharmony_ci refs_->RemoveCallback(); 4603f4cbf05Sopenharmony_ci refs_->DecRefCount(); 4613f4cbf05Sopenharmony_ci } 4623f4cbf05Sopenharmony_ci 4633f4cbf05Sopenharmony_ci refs_ = new (std::nothrow) RefCounter(); 4643f4cbf05Sopenharmony_ci if (refs_ != nullptr) { 4653f4cbf05Sopenharmony_ci refs_->IncRefCount(); 4663f4cbf05Sopenharmony_ci refs_->SetCallback([this] { this->RefPtrCallback(); }); 4673f4cbf05Sopenharmony_ci#ifndef EMULATOR_PLATFORM 4683f4cbf05Sopenharmony_ci refs_->SetCanPromote([this] { return this->CanPromote(); }); 4693f4cbf05Sopenharmony_ci#endif 4703f4cbf05Sopenharmony_ci } 4713f4cbf05Sopenharmony_ci 4723f4cbf05Sopenharmony_ci return *this; 4733f4cbf05Sopenharmony_ci} 4743f4cbf05Sopenharmony_ci 4753f4cbf05Sopenharmony_ciRefBase::RefBase(RefBase &&other) noexcept 4763f4cbf05Sopenharmony_ci{ 4773f4cbf05Sopenharmony_ci refs_ = other.refs_; 4783f4cbf05Sopenharmony_ci other.refs_ = nullptr; 4793f4cbf05Sopenharmony_ci} 4803f4cbf05Sopenharmony_ci 4813f4cbf05Sopenharmony_ciRefBase &RefBase::operator=(RefBase &&other) noexcept 4823f4cbf05Sopenharmony_ci{ 4833f4cbf05Sopenharmony_ci if (refs_ == other.refs_) { 4843f4cbf05Sopenharmony_ci return *this; 4853f4cbf05Sopenharmony_ci } 4863f4cbf05Sopenharmony_ci 4873f4cbf05Sopenharmony_ci if (refs_ != nullptr) { 4883f4cbf05Sopenharmony_ci refs_->RemoveCallback(); 4893f4cbf05Sopenharmony_ci refs_->DecRefCount(); 4903f4cbf05Sopenharmony_ci } 4913f4cbf05Sopenharmony_ci 4923f4cbf05Sopenharmony_ci refs_ = other.refs_; 4933f4cbf05Sopenharmony_ci other.refs_ = nullptr; 4943f4cbf05Sopenharmony_ci return *this; 4953f4cbf05Sopenharmony_ci} 4963f4cbf05Sopenharmony_ci 4973f4cbf05Sopenharmony_ciRefBase::~RefBase() 4983f4cbf05Sopenharmony_ci{ 4993f4cbf05Sopenharmony_ci if (refs_ != nullptr) { 5003f4cbf05Sopenharmony_ci refs_->RemoveCallback(); 5013f4cbf05Sopenharmony_ci if ((refs_->IsLifeTimeExtended() && refs_->GetWeakRefCount() == 0) || 5023f4cbf05Sopenharmony_ci refs_->GetStrongRefCount() == INITIAL_PRIMARY_VALUE) { 5033f4cbf05Sopenharmony_ci refs_->DecRefCount(); 5043f4cbf05Sopenharmony_ci } 5053f4cbf05Sopenharmony_ci refs_ = nullptr; 5063f4cbf05Sopenharmony_ci } 5073f4cbf05Sopenharmony_ci} 5083f4cbf05Sopenharmony_ci 5093f4cbf05Sopenharmony_civoid RefBase::ExtendObjectLifetime() 5103f4cbf05Sopenharmony_ci{ 5113f4cbf05Sopenharmony_ci refs_->ExtendObjectLifetime(); 5123f4cbf05Sopenharmony_ci} 5133f4cbf05Sopenharmony_ci 5143f4cbf05Sopenharmony_civoid RefBase::IncStrongRef(const void *objectId) 5153f4cbf05Sopenharmony_ci{ 5163f4cbf05Sopenharmony_ci if (refs_ == nullptr) { 5173f4cbf05Sopenharmony_ci return; 5183f4cbf05Sopenharmony_ci } 5193f4cbf05Sopenharmony_ci 5203f4cbf05Sopenharmony_ci IncWeakRef(objectId); 5213f4cbf05Sopenharmony_ci const int curCount = refs_->IncStrongRefCount(objectId); 5223f4cbf05Sopenharmony_ci if (!refs_->IsLifeTimeExtended() && curCount == 0) { 5233f4cbf05Sopenharmony_ci UTILS_LOGF("%{public}p still incStrongRef after last strong ref", this); 5243f4cbf05Sopenharmony_ci } 5253f4cbf05Sopenharmony_ci if (curCount == INITIAL_PRIMARY_VALUE) { 5263f4cbf05Sopenharmony_ci OnFirstStrongRef(objectId); 5273f4cbf05Sopenharmony_ci } 5283f4cbf05Sopenharmony_ci} 5293f4cbf05Sopenharmony_ci 5303f4cbf05Sopenharmony_civoid RefBase::CheckIsAttemptAcquireSet(const void *objectId) 5313f4cbf05Sopenharmony_ci{ 5323f4cbf05Sopenharmony_ci if (refs_->IsAttemptAcquireSet()) { 5333f4cbf05Sopenharmony_ci refs_->ClearAttemptAcquire(); 5343f4cbf05Sopenharmony_ci const int attemptCount = refs_->GetAttemptAcquire(); 5353f4cbf05Sopenharmony_ci if (attemptCount < 0) { 5363f4cbf05Sopenharmony_ci UTILS_LOGF("Multi-threads trigger illegal decstrong from %{public}d due to AttemptIncStrong in ipc", 5373f4cbf05Sopenharmony_ci attemptCount); 5383f4cbf05Sopenharmony_ci } 5393f4cbf05Sopenharmony_ci refs_->DecStrongRefCount(objectId); 5403f4cbf05Sopenharmony_ci refs_->DecWeakRefCount(objectId); 5413f4cbf05Sopenharmony_ci } 5423f4cbf05Sopenharmony_ci} 5433f4cbf05Sopenharmony_ci 5443f4cbf05Sopenharmony_civoid RefBase::DecStrongRef(const void *objectId) 5453f4cbf05Sopenharmony_ci{ 5463f4cbf05Sopenharmony_ci if (refs_ == nullptr) { 5473f4cbf05Sopenharmony_ci return; 5483f4cbf05Sopenharmony_ci } 5493f4cbf05Sopenharmony_ci 5503f4cbf05Sopenharmony_ci RefCounter * const refs = refs_; 5513f4cbf05Sopenharmony_ci const int curCount = refs->DecStrongRefCount(objectId); 5523f4cbf05Sopenharmony_ci if (curCount <= 0) { 5533f4cbf05Sopenharmony_ci UTILS_LOGF("%{public}p call decStrongRef too many times", this); 5543f4cbf05Sopenharmony_ci } 5553f4cbf05Sopenharmony_ci if (curCount == 1) { 5563f4cbf05Sopenharmony_ci std::atomic_thread_fence(std::memory_order_acquire); 5573f4cbf05Sopenharmony_ci OnLastStrongRef(objectId); 5583f4cbf05Sopenharmony_ci if (!refs->IsLifeTimeExtended()) { 5593f4cbf05Sopenharmony_ci if (refs->callback_) { 5603f4cbf05Sopenharmony_ci refs->callback_(); 5613f4cbf05Sopenharmony_ci } 5623f4cbf05Sopenharmony_ci } 5633f4cbf05Sopenharmony_ci } 5643f4cbf05Sopenharmony_ci 5653f4cbf05Sopenharmony_ci refs->DecWeakRefCount(objectId); 5663f4cbf05Sopenharmony_ci} 5673f4cbf05Sopenharmony_ci 5683f4cbf05Sopenharmony_ciint RefBase::GetSptrRefCount() 5693f4cbf05Sopenharmony_ci{ 5703f4cbf05Sopenharmony_ci if (refs_ == nullptr) { 5713f4cbf05Sopenharmony_ci return 0; 5723f4cbf05Sopenharmony_ci } 5733f4cbf05Sopenharmony_ci return refs_->GetStrongRefCount(); 5743f4cbf05Sopenharmony_ci} 5753f4cbf05Sopenharmony_ci 5763f4cbf05Sopenharmony_ciWeakRefCounter *RefBase::CreateWeakRef(void *cookie) 5773f4cbf05Sopenharmony_ci{ 5783f4cbf05Sopenharmony_ci if (refs_ != nullptr) { 5793f4cbf05Sopenharmony_ci return new WeakRefCounter(refs_, cookie); 5803f4cbf05Sopenharmony_ci } 5813f4cbf05Sopenharmony_ci return nullptr; 5823f4cbf05Sopenharmony_ci} 5833f4cbf05Sopenharmony_ci 5843f4cbf05Sopenharmony_civoid RefBase::IncWeakRef(const void *objectId) 5853f4cbf05Sopenharmony_ci{ 5863f4cbf05Sopenharmony_ci if (refs_ != nullptr) { 5873f4cbf05Sopenharmony_ci refs_->IncWeakRefCount(objectId); 5883f4cbf05Sopenharmony_ci } 5893f4cbf05Sopenharmony_ci} 5903f4cbf05Sopenharmony_ci 5913f4cbf05Sopenharmony_ciRefCounter *RefBase::GetRefCounter() const 5923f4cbf05Sopenharmony_ci{ 5933f4cbf05Sopenharmony_ci return refs_; 5943f4cbf05Sopenharmony_ci} 5953f4cbf05Sopenharmony_ci 5963f4cbf05Sopenharmony_civoid RefBase::DecWeakRef(const void *objectId) 5973f4cbf05Sopenharmony_ci{ 5983f4cbf05Sopenharmony_ci if (refs_ != nullptr) { 5993f4cbf05Sopenharmony_ci refs_->DecWeakRefCount(objectId); 6003f4cbf05Sopenharmony_ci } 6013f4cbf05Sopenharmony_ci} 6023f4cbf05Sopenharmony_ci 6033f4cbf05Sopenharmony_ciint RefBase::GetWptrRefCount() 6043f4cbf05Sopenharmony_ci{ 6053f4cbf05Sopenharmony_ci if (refs_ == nullptr) { 6063f4cbf05Sopenharmony_ci return 0; 6073f4cbf05Sopenharmony_ci } 6083f4cbf05Sopenharmony_ci return refs_->GetWeakRefCount(); 6093f4cbf05Sopenharmony_ci} 6103f4cbf05Sopenharmony_ci 6113f4cbf05Sopenharmony_cibool RefBase::AttemptAcquire(const void *objectId) 6123f4cbf05Sopenharmony_ci{ 6133f4cbf05Sopenharmony_ci if (refs_ == nullptr) { 6143f4cbf05Sopenharmony_ci return false; 6153f4cbf05Sopenharmony_ci } 6163f4cbf05Sopenharmony_ci 6173f4cbf05Sopenharmony_ci int count = 0; 6183f4cbf05Sopenharmony_ci if (refs_->AttemptIncStrongRef(objectId, count)) { 6193f4cbf05Sopenharmony_ci refs_->SetAttemptAcquire(); 6203f4cbf05Sopenharmony_ci if (count == INITIAL_PRIMARY_VALUE) { 6213f4cbf05Sopenharmony_ci OnFirstStrongRef(objectId); 6223f4cbf05Sopenharmony_ci } 6233f4cbf05Sopenharmony_ci 6243f4cbf05Sopenharmony_ci return true; 6253f4cbf05Sopenharmony_ci } 6263f4cbf05Sopenharmony_ci return false; 6273f4cbf05Sopenharmony_ci} 6283f4cbf05Sopenharmony_ci 6293f4cbf05Sopenharmony_cibool RefBase::AttemptIncStrongRef(const void *objectId) 6303f4cbf05Sopenharmony_ci{ 6313f4cbf05Sopenharmony_ci if ((refs_ != nullptr) && (OnAttemptPromoted(objectId))) { 6323f4cbf05Sopenharmony_ci int count = 0; 6333f4cbf05Sopenharmony_ci bool ret = refs_->AttemptIncStrongRef(objectId, count); 6343f4cbf05Sopenharmony_ci if (count == INITIAL_PRIMARY_VALUE) { 6353f4cbf05Sopenharmony_ci OnFirstStrongRef(objectId); 6363f4cbf05Sopenharmony_ci } 6373f4cbf05Sopenharmony_ci return ret; 6383f4cbf05Sopenharmony_ci } 6393f4cbf05Sopenharmony_ci 6403f4cbf05Sopenharmony_ci return false; 6413f4cbf05Sopenharmony_ci} 6423f4cbf05Sopenharmony_ci 6433f4cbf05Sopenharmony_cibool RefBase::AttemptIncStrong(const void *objectId) 6443f4cbf05Sopenharmony_ci{ 6453f4cbf05Sopenharmony_ci if (refs_ == nullptr) { 6463f4cbf05Sopenharmony_ci return false; 6473f4cbf05Sopenharmony_ci } 6483f4cbf05Sopenharmony_ci if (refs_->AttemptIncStrong(objectId)) { 6493f4cbf05Sopenharmony_ci refs_->SetAttemptAcquire(); 6503f4cbf05Sopenharmony_ci return true; 6513f4cbf05Sopenharmony_ci } 6523f4cbf05Sopenharmony_ci return false; 6533f4cbf05Sopenharmony_ci} 6543f4cbf05Sopenharmony_ci 6553f4cbf05Sopenharmony_cibool RefBase::IsAttemptAcquireSet() 6563f4cbf05Sopenharmony_ci{ 6573f4cbf05Sopenharmony_ci if (refs_ == nullptr) { 6583f4cbf05Sopenharmony_ci return false; 6593f4cbf05Sopenharmony_ci } 6603f4cbf05Sopenharmony_ci return refs_->IsAttemptAcquireSet(); 6613f4cbf05Sopenharmony_ci} 6623f4cbf05Sopenharmony_ci 6633f4cbf05Sopenharmony_cibool RefBase::IsExtendLifeTimeSet() 6643f4cbf05Sopenharmony_ci{ 6653f4cbf05Sopenharmony_ci if (refs_ == nullptr) { 6663f4cbf05Sopenharmony_ci return false; 6673f4cbf05Sopenharmony_ci } 6683f4cbf05Sopenharmony_ci return refs_->IsLifeTimeExtended(); 6693f4cbf05Sopenharmony_ci} 6703f4cbf05Sopenharmony_ci 6713f4cbf05Sopenharmony_civoid RefBase::OnFirstStrongRef(const void*) 6723f4cbf05Sopenharmony_ci{} 6733f4cbf05Sopenharmony_ci 6743f4cbf05Sopenharmony_civoid RefBase::OnLastStrongRef(const void*) 6753f4cbf05Sopenharmony_ci{} 6763f4cbf05Sopenharmony_ci 6773f4cbf05Sopenharmony_civoid RefBase::OnLastWeakRef(const void*) 6783f4cbf05Sopenharmony_ci{} 6793f4cbf05Sopenharmony_ci 6803f4cbf05Sopenharmony_cibool RefBase::OnAttemptPromoted(const void*) 6813f4cbf05Sopenharmony_ci{ 6823f4cbf05Sopenharmony_ci return true; 6833f4cbf05Sopenharmony_ci} 6843f4cbf05Sopenharmony_ci 6853f4cbf05Sopenharmony_ci#if ((defined DEBUG_REFBASE) && (!defined TRACK_ALL)) 6863f4cbf05Sopenharmony_civoid RefBase::EnableTracker() 6873f4cbf05Sopenharmony_ci{ 6883f4cbf05Sopenharmony_ci refs_->EnableTracker(); 6893f4cbf05Sopenharmony_ci} 6903f4cbf05Sopenharmony_ci#else 6913f4cbf05Sopenharmony_civoid RefBase::EnableTracker() 6923f4cbf05Sopenharmony_ci{ 6933f4cbf05Sopenharmony_ci} 6943f4cbf05Sopenharmony_ci#endif 6953f4cbf05Sopenharmony_ci 6963f4cbf05Sopenharmony_ci} // namespace OHOS 697