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