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