1e9297d28Sopenharmony_ci/*
2e9297d28Sopenharmony_ci * Copyright (c) 2021-2022 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 /**
17e9297d28Sopenharmony_ci * @file refbase.h
18e9297d28Sopenharmony_ci *
19e9297d28Sopenharmony_ci * @brief Provide smart pointer implemented in c_utils.
20e9297d28Sopenharmony_ci */
21e9297d28Sopenharmony_ci
22e9297d28Sopenharmony_ci /**
23e9297d28Sopenharmony_ci  * @defgroup SmartPointer
24e9297d28Sopenharmony_ci  * @{
25e9297d28Sopenharmony_ci  * @brief Smart Pointer are pointer-like classes.
26e9297d28Sopenharmony_ci  *
27e9297d28Sopenharmony_ci  * They simulates a pointer while providing added features,
28e9297d28Sopenharmony_ci  * such as automatic memory management.\n
29e9297d28Sopenharmony_ci  * Automatic memory management is mainly about deallocating
30e9297d28Sopenharmony_ci  * the related memory correctly when an object beyonds its life cycle.
31e9297d28Sopenharmony_ci  */
32e9297d28Sopenharmony_ci
33e9297d28Sopenharmony_ci#ifndef UTILS_BASE_REFBASE_H
34e9297d28Sopenharmony_ci#define UTILS_BASE_REFBASE_H
35e9297d28Sopenharmony_ci
36e9297d28Sopenharmony_ci#include <atomic>
37e9297d28Sopenharmony_ci#include <functional>
38e9297d28Sopenharmony_ci#ifdef DEBUG_REFBASE
39e9297d28Sopenharmony_ci#include <mutex>
40e9297d28Sopenharmony_ci#endif
41e9297d28Sopenharmony_ci
42e9297d28Sopenharmony_ci#ifdef _WIN32
43e9297d28Sopenharmony_ci#define RS_EXPORT __attribute__((dllexport))
44e9297d28Sopenharmony_ci#else
45e9297d28Sopenharmony_ci#define RS_EXPORT __attribute__((visibility("default")))
46e9297d28Sopenharmony_ci#endif
47e9297d28Sopenharmony_ci
48e9297d28Sopenharmony_cinamespace OHOS {
49e9297d28Sopenharmony_ci/**
50e9297d28Sopenharmony_ci * @ingroup SmartPointer
51e9297d28Sopenharmony_ci * @brief A value indicates no strong references exist ever.
52e9297d28Sopenharmony_ci */
53e9297d28Sopenharmony_ci#define INITIAL_PRIMARY_VALUE (1 << 28)
54e9297d28Sopenharmony_ci
55e9297d28Sopenharmony_ciclass RefBase;
56e9297d28Sopenharmony_ci
57e9297d28Sopenharmony_ci#ifdef DEBUG_REFBASE
58e9297d28Sopenharmony_ciclass RefTracker;
59e9297d28Sopenharmony_ci#endif
60e9297d28Sopenharmony_ci
61e9297d28Sopenharmony_ci/**
62e9297d28Sopenharmony_ci * @ingroup SmartPointer
63e9297d28Sopenharmony_ci * @brief Reference counter. A class records two kinds of count of references to
64e9297d28Sopenharmony_ci * the corresponding RefBase object, and a count of references to the RefCounter
65e9297d28Sopenharmony_ci * itself.
66e9297d28Sopenharmony_ci *
67e9297d28Sopenharmony_ci * There are two different references for a single object.\n
68e9297d28Sopenharmony_ci * Strong Reference holds a reference directly point to the object.
69e9297d28Sopenharmony_ci * Objects which are strong referenced ought to be alive/existed
70e9297d28Sopenharmony_ci * as long as this strong reference exists, thus the reference
71e9297d28Sopenharmony_ci * is still valid.\n
72e9297d28Sopenharmony_ci * Weak Reference holds a reference indirectly point to the object.
73e9297d28Sopenharmony_ci * Objects which are weak referenced are not guaranteed to be alive/existed
74e9297d28Sopenharmony_ci * even if the weak reference exists.
75e9297d28Sopenharmony_ci * @note Descriptions above are valid only when smart pointers
76e9297d28Sopenharmony_ci * are properly used.
77e9297d28Sopenharmony_ci */
78e9297d28Sopenharmony_ciclass RefCounter {
79e9297d28Sopenharmony_cipublic:
80e9297d28Sopenharmony_ci    /**
81e9297d28Sopenharmony_ci     * @brief Callback function to destroy the corresponding RefBase object.
82e9297d28Sopenharmony_ci     */
83e9297d28Sopenharmony_ci    using RefPtrCallback = std::function<void()>;
84e9297d28Sopenharmony_ci    friend class RefBase;
85e9297d28Sopenharmony_ci
86e9297d28Sopenharmony_ci    RefCounter();
87e9297d28Sopenharmony_ci
88e9297d28Sopenharmony_ci    explicit RefCounter(RefCounter *counter);
89e9297d28Sopenharmony_ci
90e9297d28Sopenharmony_ci    RefCounter &operator=(const RefCounter &counter);
91e9297d28Sopenharmony_ci
92e9297d28Sopenharmony_ci    virtual ~RefCounter();
93e9297d28Sopenharmony_ci
94e9297d28Sopenharmony_ci    /**
95e9297d28Sopenharmony_ci     * @brief Set the callback function.
96e9297d28Sopenharmony_ci     *
97e9297d28Sopenharmony_ci     * @param callback A function to be set to delete
98e9297d28Sopenharmony_ci     * the corresponding RefBase object.
99e9297d28Sopenharmony_ci     */
100e9297d28Sopenharmony_ci    void SetCallback(const RefPtrCallback& callback);
101e9297d28Sopenharmony_ci
102e9297d28Sopenharmony_ci    /**
103e9297d28Sopenharmony_ci     * @brief Remove the current callback function. Set it to a `nullptr`.
104e9297d28Sopenharmony_ci     */
105e9297d28Sopenharmony_ci    void RemoveCallback();
106e9297d28Sopenharmony_ci
107e9297d28Sopenharmony_ci    /**
108e9297d28Sopenharmony_ci     * @brief Get reference count to the RefCounter object.
109e9297d28Sopenharmony_ci     *
110e9297d28Sopenharmony_ci     * @return Value of the related count.
111e9297d28Sopenharmony_ci     */
112e9297d28Sopenharmony_ci    int GetRefCount();
113e9297d28Sopenharmony_ci
114e9297d28Sopenharmony_ci    /**
115e9297d28Sopenharmony_ci     * @brief Increment the reference count to the RefCounter object by 1.
116e9297d28Sopenharmony_ci     */
117e9297d28Sopenharmony_ci    void IncRefCount();
118e9297d28Sopenharmony_ci
119e9297d28Sopenharmony_ci    /**
120e9297d28Sopenharmony_ci     * @brief Decrement the reference count to the RefCounter object by 1.
121e9297d28Sopenharmony_ci     *
122e9297d28Sopenharmony_ci     * Once the count reaches 0 after being decremented,
123e9297d28Sopenharmony_ci     * it will call `delete this` to deallocate this RefCounter object.
124e9297d28Sopenharmony_ci     */
125e9297d28Sopenharmony_ci    void DecRefCount();
126e9297d28Sopenharmony_ci
127e9297d28Sopenharmony_ci    /**
128e9297d28Sopenharmony_ci     * @brief Check if pointer to the call back function is a `nullptr`.
129e9297d28Sopenharmony_ci     *
130e9297d28Sopenharmony_ci     * @return Return true if it is not a `nullptr`.
131e9297d28Sopenharmony_ci     */
132e9297d28Sopenharmony_ci    bool IsRefPtrValid();
133e9297d28Sopenharmony_ci
134e9297d28Sopenharmony_ci    /**
135e9297d28Sopenharmony_ci     * @brief Increment the strong reference count to the
136e9297d28Sopenharmony_ci     * corresponding RefBase object by 1.
137e9297d28Sopenharmony_ci     *
138e9297d28Sopenharmony_ci     * @return Original (before increment) value of the count.
139e9297d28Sopenharmony_ci     */
140e9297d28Sopenharmony_ci    int IncStrongRefCount(const void *objectId);
141e9297d28Sopenharmony_ci
142e9297d28Sopenharmony_ci    /**
143e9297d28Sopenharmony_ci     * @brief Decrement the strong reference count to the
144e9297d28Sopenharmony_ci     * corresponding RefBase object by 1.
145e9297d28Sopenharmony_ci     *
146e9297d28Sopenharmony_ci     * @return Original (before decrement) value of the count.
147e9297d28Sopenharmony_ci     * @note If the strong reference has never existed,
148e9297d28Sopenharmony_ci     * decrement will cause no effection.
149e9297d28Sopenharmony_ci     */
150e9297d28Sopenharmony_ci    int DecStrongRefCount(const void *objectId);
151e9297d28Sopenharmony_ci
152e9297d28Sopenharmony_ci    /**
153e9297d28Sopenharmony_ci     * @brief Get the strong reference count to the
154e9297d28Sopenharmony_ci     * corresponding RefBase object.
155e9297d28Sopenharmony_ci     *
156e9297d28Sopenharmony_ci     * @return Value of the related count.
157e9297d28Sopenharmony_ci     */
158e9297d28Sopenharmony_ci    int GetStrongRefCount();
159e9297d28Sopenharmony_ci
160e9297d28Sopenharmony_ci    /**
161e9297d28Sopenharmony_ci     * @brief Increment the weak reference count to the
162e9297d28Sopenharmony_ci     * corresponding RefBase object by 1.
163e9297d28Sopenharmony_ci     *
164e9297d28Sopenharmony_ci     * @return Original (before increment) value of the count.
165e9297d28Sopenharmony_ci     */
166e9297d28Sopenharmony_ci    int IncWeakRefCount(const void *objectId);
167e9297d28Sopenharmony_ci
168e9297d28Sopenharmony_ci    /**
169e9297d28Sopenharmony_ci     * @brief Decrement the weak reference count to the
170e9297d28Sopenharmony_ci     * corresponding RefBase object by 1.
171e9297d28Sopenharmony_ci     *
172e9297d28Sopenharmony_ci     * @return Original (before decrement) value of atomicWeak_.
173e9297d28Sopenharmony_ci     * @note When the count reaches 0 after being decremented, the
174e9297d28Sopenharmony_ci     * corresponding RefBase object with no strong reference ever,
175e9297d28Sopenharmony_ci     * or the object with strong reference count of 0 but has not been
176e9297d28Sopenharmony_ci     * deallocated due to its extended 'life time', will be deallocated.
177e9297d28Sopenharmony_ci     */
178e9297d28Sopenharmony_ci    int DecWeakRefCount(const void *objectId);
179e9297d28Sopenharmony_ci
180e9297d28Sopenharmony_ci    /**
181e9297d28Sopenharmony_ci     * @brief Get the weak reference count to the
182e9297d28Sopenharmony_ci     * corresponding RefBase object.
183e9297d28Sopenharmony_ci     *
184e9297d28Sopenharmony_ci     * @return Value of the related count.
185e9297d28Sopenharmony_ci     */
186e9297d28Sopenharmony_ci    int GetWeakRefCount();
187e9297d28Sopenharmony_ci
188e9297d28Sopenharmony_ci    /**
189e9297d28Sopenharmony_ci     * @brief Increment the times of attempts to increment.
190e9297d28Sopenharmony_ci     */
191e9297d28Sopenharmony_ci    void SetAttemptAcquire();
192e9297d28Sopenharmony_ci
193e9297d28Sopenharmony_ci    /**
194e9297d28Sopenharmony_ci     * @brief Check if the times of attempts greater than 0.
195e9297d28Sopenharmony_ci     *
196e9297d28Sopenharmony_ci     * @return Return true if the times is greater than 0.
197e9297d28Sopenharmony_ci     */
198e9297d28Sopenharmony_ci    bool IsAttemptAcquireSet();
199e9297d28Sopenharmony_ci
200e9297d28Sopenharmony_ci    /**
201e9297d28Sopenharmony_ci     * @brief Clear the times of attempts to increment.
202e9297d28Sopenharmony_ci     */
203e9297d28Sopenharmony_ci    void ClearAttemptAcquire();
204e9297d28Sopenharmony_ci
205e9297d28Sopenharmony_ci    /**
206e9297d28Sopenharmony_ci     * @brief Attempt to increment the strong reference count to the
207e9297d28Sopenharmony_ci     * corresponding RefBase object by 1.
208e9297d28Sopenharmony_ci     *
209e9297d28Sopenharmony_ci     * @param outCount If the attempt success, the original value
210e9297d28Sopenharmony_ci     * (before increment) of the count will be stored here.
211e9297d28Sopenharmony_ci     * @return Return true if the attempt success.
212e9297d28Sopenharmony_ci     */
213e9297d28Sopenharmony_ci    bool AttemptIncStrongRef(const void *objectId, int &outCount);
214e9297d28Sopenharmony_ci
215e9297d28Sopenharmony_ci    // Only for IPC use.
216e9297d28Sopenharmony_ci    /**
217e9297d28Sopenharmony_ci     * @brief Attempt to increment the strong reference count to
218e9297d28Sopenharmony_ci     * the corresponding RefBase object by 1(Simplified).
219e9297d28Sopenharmony_ci     *
220e9297d28Sopenharmony_ci     * @return Return true if the attempt success.
221e9297d28Sopenharmony_ci     * @note  Ony for IPC use.
222e9297d28Sopenharmony_ci     */
223e9297d28Sopenharmony_ci    bool AttemptIncStrong(const void *objectId);
224e9297d28Sopenharmony_ci
225e9297d28Sopenharmony_ci    /**
226e9297d28Sopenharmony_ci     * @brief Check if the corresponding RefBase object
227e9297d28Sopenharmony_ci     * own an extended life-time.
228e9297d28Sopenharmony_ci     *
229e9297d28Sopenharmony_ci     * @return Return true if its life-time has been extended.
230e9297d28Sopenharmony_ci     */
231e9297d28Sopenharmony_ci    bool IsLifeTimeExtended();
232e9297d28Sopenharmony_ci
233e9297d28Sopenharmony_ci    /**
234e9297d28Sopenharmony_ci     * @brief Extend the life-time of corresponding RefBase object.
235e9297d28Sopenharmony_ci     *
236e9297d28Sopenharmony_ci     * It allows the corresponding object keep alive
237e9297d28Sopenharmony_ci     * even if there exists no strong reference to it.
238e9297d28Sopenharmony_ci     * @note Corresponding object will be deallocated
239e9297d28Sopenharmony_ci     * when related weak reference count also reach 0.
240e9297d28Sopenharmony_ci     */
241e9297d28Sopenharmony_ci    void ExtendObjectLifetime();
242e9297d28Sopenharmony_ci
243e9297d28Sopenharmony_ciprivate:
244e9297d28Sopenharmony_ci    std::atomic<int> atomicStrong_; // = (num of sptr) or Initial-value
245e9297d28Sopenharmony_ci    std::atomic<int> atomicWeak_; // = (num of sptr)+(num of WeakRefCounter)
246e9297d28Sopenharmony_ci    std::atomic<int> atomicRefCount_; // = (num of WeakRefCounter) + 1
247e9297d28Sopenharmony_ci    std::atomic<unsigned int> atomicFlags_; // A life-time extended flag
248e9297d28Sopenharmony_ci    std::atomic<int> atomicAttempt_; // Times of attempts
249e9297d28Sopenharmony_ci    RefPtrCallback callback_ = nullptr; // A callback function to deallocate the corresponding RefBase object
250e9297d28Sopenharmony_ci    static constexpr unsigned int FLAG_EXTEND_LIFE_TIME = 0x00000002; // Extended life-time bit to be set via logic-OR
251e9297d28Sopenharmony_ci#ifdef DEBUG_REFBASE
252e9297d28Sopenharmony_ci    RefTracker* refTracker = nullptr;
253e9297d28Sopenharmony_ci    std::mutex trackerMutex;  // To ensure refTracker be thread-safe
254e9297d28Sopenharmony_ci    void GetNewTrace(const void* objectId);
255e9297d28Sopenharmony_ci    void PrintTracker();
256e9297d28Sopenharmony_ci#endif
257e9297d28Sopenharmony_ci};
258e9297d28Sopenharmony_ci
259e9297d28Sopenharmony_ci#ifdef DEBUG_REFBASE
260e9297d28Sopenharmony_ci// RefTracker is a debug tool, used to record the trace of RefBase.
261e9297d28Sopenharmony_ci// RefTracker will save the information about the count of RefBase,
262e9297d28Sopenharmony_ci// including the pointer of sptr/wptr(The pointer of itself, not the pointer
263e9297d28Sopenharmony_ci// it manages), the amount of strong/weak/refcout and the PID&TID.
264e9297d28Sopenharmony_ci// The Tracker can live with RefCounter/RefBase(including its derivation).
265e9297d28Sopenharmony_ci// User should keep thread-safety of RefTracker.
266e9297d28Sopenharmony_ciclass RefTracker {
267e9297d28Sopenharmony_cipublic:
268e9297d28Sopenharmony_ci    RefTracker() {};
269e9297d28Sopenharmony_ci
270e9297d28Sopenharmony_ci    RefTracker(RefTracker* exTracker, const void* id, int strong, int weak, int ref, int pid, int tid);
271e9297d28Sopenharmony_ci
272e9297d28Sopenharmony_ci    void GetTrace(RefTracker* exTracker, const void* id, int strong, int weak, int ref, int pid, int tid);
273e9297d28Sopenharmony_ci
274e9297d28Sopenharmony_ci    // Only used for tracking the amount of Strong Reference.
275e9297d28Sopenharmony_ci    void GetStrongTrace(RefTracker* exTracker, const void* id, int strong, int pid, int tid);
276e9297d28Sopenharmony_ci
277e9297d28Sopenharmony_ci    // Only used for tracking the amount of Weak Reference.
278e9297d28Sopenharmony_ci    void GetWeakTrace(RefTracker* exTracker, const void* id, int weak, int pid, int tid);
279e9297d28Sopenharmony_ci
280e9297d28Sopenharmony_ci    void PrintTrace(const void* root);
281e9297d28Sopenharmony_ci
282e9297d28Sopenharmony_ci    void PrintStrongTrace(const void* root);
283e9297d28Sopenharmony_ci
284e9297d28Sopenharmony_ci    void PrintWeakTrace(const void* root);
285e9297d28Sopenharmony_ci
286e9297d28Sopenharmony_ci    RefTracker* GetexTrace();
287e9297d28Sopenharmony_ci
288e9297d28Sopenharmony_ci    RefTracker* PopTrace(const void* root);
289e9297d28Sopenharmony_ci
290e9297d28Sopenharmony_ciprivate:
291e9297d28Sopenharmony_ci    const void* ptrID;
292e9297d28Sopenharmony_ci    int strongRefCNT;
293e9297d28Sopenharmony_ci    int weakRefCNT;
294e9297d28Sopenharmony_ci    int refCNT;
295e9297d28Sopenharmony_ci    int PID;
296e9297d28Sopenharmony_ci    int TID;
297e9297d28Sopenharmony_ci    RefTracker* exTrace;
298e9297d28Sopenharmony_ci};
299e9297d28Sopenharmony_ci#endif
300e9297d28Sopenharmony_ci
301e9297d28Sopenharmony_ci/**
302e9297d28Sopenharmony_ci * @ingroup SmartPointer
303e9297d28Sopenharmony_ci * @brief An intermediate class to represent the weak reference
304e9297d28Sopenharmony_ci * to the correspond RefBase object.
305e9297d28Sopenharmony_ci *
306e9297d28Sopenharmony_ci * A WeakRefCounter object can be held by multiple wptr objects.\n
307e9297d28Sopenharmony_ci * It holds references to the corresponding RefBase and RefCounter object.
308e9297d28Sopenharmony_ci * Those two references will be set as `nullptr`s, when the weak referenced
309e9297d28Sopenharmony_ci * target and its RefCounter object has been deallocated. Thus WeakRefCounter
310e9297d28Sopenharmony_ci * object can still alive even if the target refereneced by this object
311e9297d28Sopenharmony_ci * is vanished.
312e9297d28Sopenharmony_ci */
313e9297d28Sopenharmony_ciclass WeakRefCounter {
314e9297d28Sopenharmony_cipublic:
315e9297d28Sopenharmony_ci    /**
316e9297d28Sopenharmony_ci     * @brief Construct a new Weak Ref Counter object.
317e9297d28Sopenharmony_ci     *
318e9297d28Sopenharmony_ci     * @param counter Pointer to corresponding RefCounter object.
319e9297d28Sopenharmony_ci     * @param cookie Pointer to corresponding RefBase object.
320e9297d28Sopenharmony_ci     */
321e9297d28Sopenharmony_ci    WeakRefCounter(RefCounter *counter, void *cookie);
322e9297d28Sopenharmony_ci
323e9297d28Sopenharmony_ci    virtual ~WeakRefCounter();
324e9297d28Sopenharmony_ci
325e9297d28Sopenharmony_ci    /**
326e9297d28Sopenharmony_ci     * @brief Get current pointer to the corresponding RefBase object.
327e9297d28Sopenharmony_ci     *
328e9297d28Sopenharmony_ci     * @return A void pointer to the RefBase object.
329e9297d28Sopenharmony_ci     * If the corresponding object does not alive, a `nullptr` will return.
330e9297d28Sopenharmony_ci     * @note Void pointer means you should cast it to the real type, since it
331e9297d28Sopenharmony_ci     * can be kinds of subclasses of RefBase.
332e9297d28Sopenharmony_ci     */
333e9297d28Sopenharmony_ci    void *GetRefPtr();
334e9297d28Sopenharmony_ci
335e9297d28Sopenharmony_ci    /**
336e9297d28Sopenharmony_ci     * @brief Increment the reference count to this WeakRefCounter object.
337e9297d28Sopenharmony_ci     *
338e9297d28Sopenharmony_ci     * @note Notice the difference between this count and the weak reference
339e9297d28Sopenharmony_ci     * count in RefCounter. This value equals to the number of wptrs directly
340e9297d28Sopenharmony_ci     * referencing this WeakRefCount object.
341e9297d28Sopenharmony_ci     * @see RefCounter
342e9297d28Sopenharmony_ci     */
343e9297d28Sopenharmony_ci    void IncWeakRefCount(const void *objectId);
344e9297d28Sopenharmony_ci
345e9297d28Sopenharmony_ci    /**
346e9297d28Sopenharmony_ci     * @brief Decrement the reference count to this WeakRefCounter object.
347e9297d28Sopenharmony_ci     *
348e9297d28Sopenharmony_ci     * @note This WeakRefCounter object will be deallocated when this count
349e9297d28Sopenharmony_ci     * reaches 0.
350e9297d28Sopenharmony_ci     */
351e9297d28Sopenharmony_ci    void DecWeakRefCount(const void *objectId);
352e9297d28Sopenharmony_ci
353e9297d28Sopenharmony_ci    /**
354e9297d28Sopenharmony_ci     * @brief Get the count recorded by this WeakRefCounter object.
355e9297d28Sopenharmony_ci     *
356e9297d28Sopenharmony_ci     * @return Value of the count.
357e9297d28Sopenharmony_ci     * @note This value of count is different from that in RefCounter.
358e9297d28Sopenharmony_ci     * @see RefCounter::GetWeakRefCount()
359e9297d28Sopenharmony_ci     */
360e9297d28Sopenharmony_ci    int GetWeakRefCount() const;
361e9297d28Sopenharmony_ci
362e9297d28Sopenharmony_ci    /**
363e9297d28Sopenharmony_ci     * @brief Attempt to increment the strong reference count of
364e9297d28Sopenharmony_ci     * the corresponding RefBase object(Used in promoting a wptr to a sptr).
365e9297d28Sopenharmony_ci     *
366e9297d28Sopenharmony_ci     * @return Return `true` after a success increment.
367e9297d28Sopenharmony_ci     */
368e9297d28Sopenharmony_ci    bool AttemptIncStrongRef(const void *objectId);
369e9297d28Sopenharmony_ci
370e9297d28Sopenharmony_ciprivate:
371e9297d28Sopenharmony_ci    std::atomic<int> atomicWeak_; // Count of references to this WeakRefCounter object
372e9297d28Sopenharmony_ci                                  // The value equals to the total amount of wptrs which
373e9297d28Sopenharmony_ci                                  // reference this WeakRefCounter object
374e9297d28Sopenharmony_ci    RefCounter *refCounter_ = nullptr; // reference to the RefCounter object of corresponding RefBase Object
375e9297d28Sopenharmony_ci    void *cookie_ = nullptr; // Pointer to the corresponding RefBase object
376e9297d28Sopenharmony_ci};
377e9297d28Sopenharmony_ci
378e9297d28Sopenharmony_ci/**
379e9297d28Sopenharmony_ci * @ingroup SmartPointer
380e9297d28Sopenharmony_ci * @brief A base class which can be managed by a smart pointer.
381e9297d28Sopenharmony_ci *
382e9297d28Sopenharmony_ci * @note All classes which intend to be managed by smart pointers should be
383e9297d28Sopenharmony_ci * derived from RefBase.
384e9297d28Sopenharmony_ci */
385e9297d28Sopenharmony_ciclass RS_EXPORT RefBase {
386e9297d28Sopenharmony_cipublic:
387e9297d28Sopenharmony_ci    RefBase();
388e9297d28Sopenharmony_ci
389e9297d28Sopenharmony_ci    /**
390e9297d28Sopenharmony_ci     * @brief Copy constructor of RefBase.
391e9297d28Sopenharmony_ci     *
392e9297d28Sopenharmony_ci     * @note  Note that this method will construct a new RefCounter object,
393e9297d28Sopenharmony_ci     * and bind with it.
394e9297d28Sopenharmony_ci     */
395e9297d28Sopenharmony_ci    RefBase(const RefBase &);
396e9297d28Sopenharmony_ci
397e9297d28Sopenharmony_ci    /**
398e9297d28Sopenharmony_ci     * @brief Copy assignment operator of RefBase.
399e9297d28Sopenharmony_ci     *
400e9297d28Sopenharmony_ci     * @note This method will unbind the current RefBase object and its
401e9297d28Sopenharmony_ci     * original RefCounter object, then bind a newly constructed
402e9297d28Sopenharmony_ci     * RefCounter object.
403e9297d28Sopenharmony_ci     */
404e9297d28Sopenharmony_ci    RefBase &operator=(const RefBase &);
405e9297d28Sopenharmony_ci
406e9297d28Sopenharmony_ci    /**
407e9297d28Sopenharmony_ci     * @brief Move constructor of RefBase.
408e9297d28Sopenharmony_ci     */
409e9297d28Sopenharmony_ci    RefBase(RefBase &&other) noexcept;
410e9297d28Sopenharmony_ci
411e9297d28Sopenharmony_ci    /**
412e9297d28Sopenharmony_ci     * @brief Move assignment operator of RefBase.
413e9297d28Sopenharmony_ci     *
414e9297d28Sopenharmony_ci     * @note  This method will bind this RefBase object with the RefCounter
415e9297d28Sopenharmony_ci     * object of the argument `other`, then `other` will unbind the RefCounter
416e9297d28Sopenharmony_ci     * object.\n No counts operation will be poccessed.
417e9297d28Sopenharmony_ci     */
418e9297d28Sopenharmony_ci    RefBase &operator=(RefBase &&other) noexcept;
419e9297d28Sopenharmony_ci
420e9297d28Sopenharmony_ci    virtual ~RefBase();
421e9297d28Sopenharmony_ci
422e9297d28Sopenharmony_ci    /**
423e9297d28Sopenharmony_ci     * @brief A callback method to deallocate this object.
424e9297d28Sopenharmony_ci     *
425e9297d28Sopenharmony_ci     * This method has default implement to simply deallocate this RefBase
426e9297d28Sopenharmony_ci     * object simply by calling `delete(this)`.
427e9297d28Sopenharmony_ci     */
428e9297d28Sopenharmony_ci    virtual void RefPtrCallback();
429e9297d28Sopenharmony_ci
430e9297d28Sopenharmony_ci    /**
431e9297d28Sopenharmony_ci     * @brief Extend life time of the RefBase object.
432e9297d28Sopenharmony_ci     *
433e9297d28Sopenharmony_ci     * @note The object whose life time has been extended will not be
434e9297d28Sopenharmony_ci     * deallocated when the the weak reference count reach 0 instead of the
435e9297d28Sopenharmony_ci     * strong one.
436e9297d28Sopenharmony_ci     */
437e9297d28Sopenharmony_ci    void ExtendObjectLifetime();
438e9297d28Sopenharmony_ci
439e9297d28Sopenharmony_ci    /**
440e9297d28Sopenharmony_ci     * @brief Increment the strong reference count.
441e9297d28Sopenharmony_ci     *
442e9297d28Sopenharmony_ci     * `OnFirstStrongRef()`, which is an empty method by default, will be
443e9297d28Sopenharmony_ci     * called when the first strong reference are established.、
444e9297d28Sopenharmony_ci     *
445e9297d28Sopenharmony_ci     * @note It will atomically increment the weak reference count meanwhile.
446e9297d28Sopenharmony_ci     */
447e9297d28Sopenharmony_ci    void IncStrongRef(const void *objectId);
448e9297d28Sopenharmony_ci
449e9297d28Sopenharmony_ci    /**
450e9297d28Sopenharmony_ci     * @brief Decrement the strong reference count.
451e9297d28Sopenharmony_ci     *
452e9297d28Sopenharmony_ci     * This object will be deallocated when the count reaches 0, if it owns a
453e9297d28Sopenharmony_ci     * normal life time.\n `OnLastStrongRef()`, which is an empty method by
454e9297d28Sopenharmony_ci     * default, will be called when the last strong reference vanishes.
455e9297d28Sopenharmony_ci     */
456e9297d28Sopenharmony_ci    void DecStrongRef(const void *objectId);
457e9297d28Sopenharmony_ci
458e9297d28Sopenharmony_ci    /**
459e9297d28Sopenharmony_ci     * @brief Get the strong reference count.
460e9297d28Sopenharmony_ci     *
461e9297d28Sopenharmony_ci     * @return Related count value. Return 0 when corresponding RefCounter
462e9297d28Sopenharmony_ci     * object does not exist.
463e9297d28Sopenharmony_ci     * @note Only valid when corresponding RefCounter object exists.
464e9297d28Sopenharmony_ci     */
465e9297d28Sopenharmony_ci    int GetSptrRefCount();
466e9297d28Sopenharmony_ci
467e9297d28Sopenharmony_ci   /**
468e9297d28Sopenharmony_ci    * @brief Create weak reference to this RefBase object.
469e9297d28Sopenharmony_ci    *
470e9297d28Sopenharmony_ci    * Create a WeakRefCounter object which holds reference to this RefBase
471e9297d28Sopenharmony_ci    * object and set the reference count.
472e9297d28Sopenharmony_ci    *
473e9297d28Sopenharmony_ci    * @param cookie Void pointer to this RefBase object.
474e9297d28Sopenharmony_ci    * @return Pointer to the newly created WeakRefCounter object.
475e9297d28Sopenharmony_ci    * @note Avoid using it independently. Use related methods of wptr.
476e9297d28Sopenharmony_ci    */
477e9297d28Sopenharmony_ci    WeakRefCounter *CreateWeakRef(void *cookie);
478e9297d28Sopenharmony_ci
479e9297d28Sopenharmony_ci    /**
480e9297d28Sopenharmony_ci     * @brief Get the pointer to corresponding counter object.
481e9297d28Sopenharmony_ci     *
482e9297d28Sopenharmony_ci     * @return Pointer to the counter object.
483e9297d28Sopenharmony_ci     */
484e9297d28Sopenharmony_ci    RefCounter *GetRefCounter() const;
485e9297d28Sopenharmony_ci
486e9297d28Sopenharmony_ci    /**
487e9297d28Sopenharmony_ci     * @brief Increment the weak reference count.
488e9297d28Sopenharmony_ci     *
489e9297d28Sopenharmony_ci     * @note Only valid when corresponding RefCounter object exists.
490e9297d28Sopenharmony_ci     */
491e9297d28Sopenharmony_ci    void IncWeakRef(const void *objectId);
492e9297d28Sopenharmony_ci
493e9297d28Sopenharmony_ci    /**
494e9297d28Sopenharmony_ci     * @brief Decrement the weak reference count.
495e9297d28Sopenharmony_ci     *
496e9297d28Sopenharmony_ci     * @note Only valid when corresponding RefCounter object exists.
497e9297d28Sopenharmony_ci     */
498e9297d28Sopenharmony_ci    void DecWeakRef(const void *objectId);
499e9297d28Sopenharmony_ci
500e9297d28Sopenharmony_ci    /**
501e9297d28Sopenharmony_ci     * @brief Get the weak reference count.
502e9297d28Sopenharmony_ci     *
503e9297d28Sopenharmony_ci     * @return Value of related count. Return 0 when corresponding
504e9297d28Sopenharmony_ci     * RefCounter object doesn't exist.
505e9297d28Sopenharmony_ci     */
506e9297d28Sopenharmony_ci    int GetWptrRefCount();
507e9297d28Sopenharmony_ci
508e9297d28Sopenharmony_ci    /**
509e9297d28Sopenharmony_ci     * @brief Attempt to increment the strong reference count.
510e9297d28Sopenharmony_ci     *
511e9297d28Sopenharmony_ci     * `OnFirstStrongRef()`, which is an empty method by default, will be
512e9297d28Sopenharmony_ci     * called when the first strong reference are established.
513e9297d28Sopenharmony_ci     *
514e9297d28Sopenharmony_ci     * @return Return true if successfully increment the count.
515e9297d28Sopenharmony_ci     * @note Note that count of times of attempts will increment by 1
516e9297d28Sopenharmony_ci     * after a successful increment.
517e9297d28Sopenharmony_ci     */
518e9297d28Sopenharmony_ci    bool AttemptAcquire(const void *objectId);
519e9297d28Sopenharmony_ci
520e9297d28Sopenharmony_ci    /**
521e9297d28Sopenharmony_ci     * @brief Attempt to increment the strong reference count.
522e9297d28Sopenharmony_ci     *
523e9297d28Sopenharmony_ci     * `OnFirstStrongRef()`, which is an empty method by default, will be
524e9297d28Sopenharmony_ci     * called when the first strong reference are established.
525e9297d28Sopenharmony_ci     * @return Return true if successfully increment the count.
526e9297d28Sopenharmony_ci     * @note Used in various copy constructor of sptr in scenario of
527e9297d28Sopenharmony_ci     * interaction between sptr and wptr. Avoid using it independently.
528e9297d28Sopenharmony_ci     */
529e9297d28Sopenharmony_ci    bool AttemptIncStrongRef(const void *objectId);
530e9297d28Sopenharmony_ci
531e9297d28Sopenharmony_ci    // Only for IPC use.
532e9297d28Sopenharmony_ci    /**
533e9297d28Sopenharmony_ci     * @brief Attempt to increment the strong reference count.
534e9297d28Sopenharmony_ci     *
535e9297d28Sopenharmony_ci     * @return Return true if successfully increment the count, otherwise
536e9297d28Sopenharmony_ci     * return false.
537e9297d28Sopenharmony_ci     * @note Note that times of successful attempts will increment by 1 after
538e9297d28Sopenharmony_ci     * a successful increment of the related count.
539e9297d28Sopenharmony_ci     * @note This method is a simplified version of `AttemptAcquire`, but only
540e9297d28Sopenharmony_ci     * for IPC use.
541e9297d28Sopenharmony_ci     */
542e9297d28Sopenharmony_ci    bool AttemptIncStrong(const void *objectId);
543e9297d28Sopenharmony_ci
544e9297d28Sopenharmony_ci    /**
545e9297d28Sopenharmony_ci     * @brief check if the times of successful attempts of greater than 0.
546e9297d28Sopenharmony_ci     *
547e9297d28Sopenharmony_ci     * @return Return true if times of successful attempts is greater than 0;
548e9297d28Sopenharmony_ci     * Return false if it is not greater than 0, or the corresponding
549e9297d28Sopenharmony_ci     * RefCounter object does not exist.
550e9297d28Sopenharmony_ci     */
551e9297d28Sopenharmony_ci    bool IsAttemptAcquireSet();
552e9297d28Sopenharmony_ci
553e9297d28Sopenharmony_ci    /**
554e9297d28Sopenharmony_ci     * @brief Check if the life time of this RefBase object has been extended.
555e9297d28Sopenharmony_ci     *
556e9297d28Sopenharmony_ci     * @return Return false when have a normal life time, or the corresponding
557e9297d28Sopenharmony_ci     * RefCounter object does not exist.
558e9297d28Sopenharmony_ci     */
559e9297d28Sopenharmony_ci    bool IsExtendLifeTimeSet();
560e9297d28Sopenharmony_ci
561e9297d28Sopenharmony_ci    /**
562e9297d28Sopenharmony_ci     * @brief An event-drive method, which will be automatically called when
563e9297d28Sopenharmony_ci     * first strong reference comes up.
564e9297d28Sopenharmony_ci     *
565e9297d28Sopenharmony_ci     * @note It is an empty function by default.
566e9297d28Sopenharmony_ci     */
567e9297d28Sopenharmony_ci    virtual void OnFirstStrongRef(const void *);
568e9297d28Sopenharmony_ci
569e9297d28Sopenharmony_ci    /**
570e9297d28Sopenharmony_ci     * @brief An event-drive method, which will be automatically called when
571e9297d28Sopenharmony_ci     * last strong reference eliminates.
572e9297d28Sopenharmony_ci     *
573e9297d28Sopenharmony_ci     * @note It is an empty function by default.
574e9297d28Sopenharmony_ci     */
575e9297d28Sopenharmony_ci    virtual void OnLastStrongRef(const void *);
576e9297d28Sopenharmony_ci
577e9297d28Sopenharmony_ci    /**
578e9297d28Sopenharmony_ci     * @brief An event-drive method, which will be automatically called when
579e9297d28Sopenharmony_ci     * last weak reference eliminates.
580e9297d28Sopenharmony_ci     *
581e9297d28Sopenharmony_ci     * @note It is an empty function by default.
582e9297d28Sopenharmony_ci     */
583e9297d28Sopenharmony_ci    virtual void OnLastWeakRef(const void *);
584e9297d28Sopenharmony_ci
585e9297d28Sopenharmony_ci    /**
586e9297d28Sopenharmony_ci     * @brief An event-drive method, which will be autmatically called when
587e9297d28Sopenharmony_ci     * use `wptr::Promote()`.
588e9297d28Sopenharmony_ci     *
589e9297d28Sopenharmony_ci     * @note Directly return true by default.
590e9297d28Sopenharmony_ci     * @return Return true if success, otherwise return false.
591e9297d28Sopenharmony_ci     */
592e9297d28Sopenharmony_ci    virtual bool OnAttemptPromoted(const void *);
593e9297d28Sopenharmony_ci
594e9297d28Sopenharmony_ciprivate:
595e9297d28Sopenharmony_ci    RefCounter *refs_ = nullptr; // Pointer to the corresponding reference counter of this RefBase object
596e9297d28Sopenharmony_ci};
597e9297d28Sopenharmony_ci
598e9297d28Sopenharmony_citemplate <typename T>
599e9297d28Sopenharmony_ciclass wptr;
600e9297d28Sopenharmony_ci
601e9297d28Sopenharmony_ci/**
602e9297d28Sopenharmony_ci * @ingroup SmartPointer
603e9297d28Sopenharmony_ci * @brief Strong reference smart pointer to a RefBase(or its subclass) object.
604e9297d28Sopenharmony_ci *
605e9297d28Sopenharmony_ci * It directly reference the RefBase object.
606e9297d28Sopenharmony_ci *
607e9297d28Sopenharmony_ci * @tparam T Specific class type managed by sptr. This class must inherit
608e9297d28Sopenharmony_ci * from RefBase.
609e9297d28Sopenharmony_ci */
610e9297d28Sopenharmony_citemplate <typename T>
611e9297d28Sopenharmony_ciclass sptr {
612e9297d28Sopenharmony_ci    friend class wptr<T>;
613e9297d28Sopenharmony_ci
614e9297d28Sopenharmony_cipublic:
615e9297d28Sopenharmony_ci    sptr();
616e9297d28Sopenharmony_ci
617e9297d28Sopenharmony_ci    ~sptr();
618e9297d28Sopenharmony_ci
619e9297d28Sopenharmony_ci    /**
620e9297d28Sopenharmony_ci     * @brief Constructor with specified object to be managed.
621e9297d28Sopenharmony_ci     *
622e9297d28Sopenharmony_ci     * @note Null sptr will be created if `other` is a `nullptr`.
623e9297d28Sopenharmony_ci     * @param other Object to be managed by wptr.
624e9297d28Sopenharmony_ci     */
625e9297d28Sopenharmony_ci    sptr(T *other);
626e9297d28Sopenharmony_ci
627e9297d28Sopenharmony_ci    /**
628e9297d28Sopenharmony_ci     * @brief Copy Constructor for sptr with different managed class type(T).
629e9297d28Sopenharmony_ci     *
630e9297d28Sopenharmony_ci     * @param other Input sptr object.
631e9297d28Sopenharmony_ci     */
632e9297d28Sopenharmony_ci    sptr(const sptr<T> &other);
633e9297d28Sopenharmony_ci
634e9297d28Sopenharmony_ci    /**
635e9297d28Sopenharmony_ci     * @brief Move constructor.
636e9297d28Sopenharmony_ci     *
637e9297d28Sopenharmony_ci     * @note `other` will be set to a null sptr.
638e9297d28Sopenharmony_ci     * @param other Input sptr object.
639e9297d28Sopenharmony_ci     */
640e9297d28Sopenharmony_ci    sptr(sptr<T> &&other);
641e9297d28Sopenharmony_ci
642e9297d28Sopenharmony_ci    /**
643e9297d28Sopenharmony_ci     * @brief Move assignment operator.
644e9297d28Sopenharmony_ci     *
645e9297d28Sopenharmony_ci     * @param other Input sptr object.
646e9297d28Sopenharmony_ci     * @note Original strong reference in target sptr object will be removed.
647e9297d28Sopenharmony_ci     */
648e9297d28Sopenharmony_ci    sptr<T> &operator=(sptr<T> &&other);
649e9297d28Sopenharmony_ci
650e9297d28Sopenharmony_ci    /**
651e9297d28Sopenharmony_ci     * @brief Copy Constructor for sptr with different managed class type(O).
652e9297d28Sopenharmony_ci     *
653e9297d28Sopenharmony_ci     * @tparam O Another specific class type managed by `other`.
654e9297d28Sopenharmony_ci     * @param other Input sptr object.
655e9297d28Sopenharmony_ci     */
656e9297d28Sopenharmony_ci    template <typename O>
657e9297d28Sopenharmony_ci    sptr(const sptr<O> &other);
658e9297d28Sopenharmony_ci
659e9297d28Sopenharmony_ci    /**
660e9297d28Sopenharmony_ci     * @brief Constructor only used in promote process of wptr.
661e9297d28Sopenharmony_ci     *
662e9297d28Sopenharmony_ci     * @param p WeakRefCounter object which hold the reference to the
663e9297d28Sopenharmony_ci     * managed object.
664e9297d28Sopenharmony_ci     * @param force Only used to identify from other constructor.
665e9297d28Sopenharmony_ci     */
666e9297d28Sopenharmony_ci    inline sptr(WeakRefCounter *p, bool force);
667e9297d28Sopenharmony_ci
668e9297d28Sopenharmony_ci    /**
669e9297d28Sopenharmony_ci     * @brief Get the pointer to the managed object.
670e9297d28Sopenharmony_ci     *
671e9297d28Sopenharmony_ci     * @return Pointer of the specific managed class type.
672e9297d28Sopenharmony_ci     */
673e9297d28Sopenharmony_ci    inline T *GetRefPtr() const
674e9297d28Sopenharmony_ci    {
675e9297d28Sopenharmony_ci        return refs_;
676e9297d28Sopenharmony_ci    }
677e9297d28Sopenharmony_ci
678e9297d28Sopenharmony_ci    /**
679e9297d28Sopenharmony_ci     * @brief Set the pointer to the managed object.
680e9297d28Sopenharmony_ci     *
681e9297d28Sopenharmony_ci     * @param other Another pointer object to be managed by sptr.
682e9297d28Sopenharmony_ci     * @note Avoid using independently, otherwise it will
683e9297d28Sopenharmony_ci     * cause mismatch of reference count and thus memory problems.
684e9297d28Sopenharmony_ci     */
685e9297d28Sopenharmony_ci    inline void ForceSetRefPtr(T *other);
686e9297d28Sopenharmony_ci
687e9297d28Sopenharmony_ci    /**
688e9297d28Sopenharmony_ci     * @brief Remove the reference to the managed object held by current sptr.
689e9297d28Sopenharmony_ci     *
690e9297d28Sopenharmony_ci     * @note It will make this sptr a "null sptr".
691e9297d28Sopenharmony_ci     */
692e9297d28Sopenharmony_ci    void clear();
693e9297d28Sopenharmony_ci
694e9297d28Sopenharmony_ci    /**
695e9297d28Sopenharmony_ci     * @brief Type conversion operator.
696e9297d28Sopenharmony_ci     *
697e9297d28Sopenharmony_ci     * @return Raw pointer to the managed object.
698e9297d28Sopenharmony_ci     * @note Sptr object itself will not be converted, only the member raw
699e9297d28Sopenharmony_ci     * pointer returns.
700e9297d28Sopenharmony_ci     */
701e9297d28Sopenharmony_ci    inline operator T *() const
702e9297d28Sopenharmony_ci    {
703e9297d28Sopenharmony_ci        return refs_;
704e9297d28Sopenharmony_ci    }
705e9297d28Sopenharmony_ci
706e9297d28Sopenharmony_ci    /**
707e9297d28Sopenharmony_ci     * @brief Dereference operator.
708e9297d28Sopenharmony_ci     *
709e9297d28Sopenharmony_ci     * It will return the object managed by this sptr.
710e9297d28Sopenharmony_ci     *
711e9297d28Sopenharmony_ci     * @return Return reference of specific object managed by sptr.
712e9297d28Sopenharmony_ci     */
713e9297d28Sopenharmony_ci    inline T &operator*() const
714e9297d28Sopenharmony_ci    {
715e9297d28Sopenharmony_ci        return *refs_;
716e9297d28Sopenharmony_ci    }
717e9297d28Sopenharmony_ci
718e9297d28Sopenharmony_ci    /**
719e9297d28Sopenharmony_ci     * @brief Member selection operator.
720e9297d28Sopenharmony_ci     *
721e9297d28Sopenharmony_ci     * It will return the specified member of the object managed by this sptr.
722e9297d28Sopenharmony_ci     */
723e9297d28Sopenharmony_ci    inline T *operator->() const
724e9297d28Sopenharmony_ci    {
725e9297d28Sopenharmony_ci        return refs_;
726e9297d28Sopenharmony_ci    }
727e9297d28Sopenharmony_ci
728e9297d28Sopenharmony_ci    /**
729e9297d28Sopenharmony_ci     * @brief Logical-NOT operator. Check if sptr is a "null sptr".
730e9297d28Sopenharmony_ci     *
731e9297d28Sopenharmony_ci     * @return Return true if sptr is a "null sptr".
732e9297d28Sopenharmony_ci     */
733e9297d28Sopenharmony_ci    inline bool operator!() const
734e9297d28Sopenharmony_ci    {
735e9297d28Sopenharmony_ci        return refs_ == nullptr;
736e9297d28Sopenharmony_ci    }
737e9297d28Sopenharmony_ci
738e9297d28Sopenharmony_ci    /**
739e9297d28Sopenharmony_ci     * @brief Copy assignment operator with specified object to be managed.
740e9297d28Sopenharmony_ci     *
741e9297d28Sopenharmony_ci     * @note Original reference will be removed, then new reference to the
742e9297d28Sopenharmony_ci     * input object will be established.
743e9297d28Sopenharmony_ci     * @param other Another object to be managed by this sptr.
744e9297d28Sopenharmony_ci     */
745e9297d28Sopenharmony_ci    sptr<T> &operator=(T *other);
746e9297d28Sopenharmony_ci
747e9297d28Sopenharmony_ci    /**
748e9297d28Sopenharmony_ci     * @brief Copy assignment operator for sptr with
749e9297d28Sopenharmony_ci     * same managed class type(T).
750e9297d28Sopenharmony_ci     *
751e9297d28Sopenharmony_ci     * @note Original reference will be removed, this sptr will manage the
752e9297d28Sopenharmony_ci     * same object with the input sptr object.
753e9297d28Sopenharmony_ci     * @param other Another sptr object with same managed class type(T).
754e9297d28Sopenharmony_ci     */
755e9297d28Sopenharmony_ci    sptr<T> &operator=(const sptr<T> &other);
756e9297d28Sopenharmony_ci
757e9297d28Sopenharmony_ci    /**
758e9297d28Sopenharmony_ci     * @brief Copy assignment operator for wptr with
759e9297d28Sopenharmony_ci     * same managed class type(T).
760e9297d28Sopenharmony_ci     *
761e9297d28Sopenharmony_ci     * @note Original reference will be removed, this sptr will manage the
762e9297d28Sopenharmony_ci     * same object with the input wptr object.
763e9297d28Sopenharmony_ci     * @note This may fail, then this sptr will turn to be a "null sptr".
764e9297d28Sopenharmony_ci     * @param other Another wptr object with same managed class type(T).
765e9297d28Sopenharmony_ci     */
766e9297d28Sopenharmony_ci    sptr<T> &operator=(const wptr<T> &other);
767e9297d28Sopenharmony_ci
768e9297d28Sopenharmony_ci    /**
769e9297d28Sopenharmony_ci     * @brief Copy assignment operator for sptr with
770e9297d28Sopenharmony_ci     * different managed class type(O).
771e9297d28Sopenharmony_ci     *
772e9297d28Sopenharmony_ci     * @note Original reference will be removed, this sptr will manage the
773e9297d28Sopenharmony_ci     * same object with the input sptr object.
774e9297d28Sopenharmony_ci     * @note This sptr will interpret the managed object as a type T.
775e9297d28Sopenharmony_ci     * @param other Another sptr object with different managed class type(O).
776e9297d28Sopenharmony_ci     */
777e9297d28Sopenharmony_ci    template <typename O>
778e9297d28Sopenharmony_ci    sptr<T> &operator=(const sptr<O> &other);
779e9297d28Sopenharmony_ci
780e9297d28Sopenharmony_ci    /**
781e9297d28Sopenharmony_ci     * @brief Equal-to operator between sptr and a raw pointer.
782e9297d28Sopenharmony_ci     *
783e9297d28Sopenharmony_ci     * @param other Input raw pointer.
784e9297d28Sopenharmony_ci     * @return Return true if sptr point to the same object with input
785e9297d28Sopenharmony_ci     * raw pointer.
786e9297d28Sopenharmony_ci     */
787e9297d28Sopenharmony_ci    bool operator==(const T *other) const;
788e9297d28Sopenharmony_ci
789e9297d28Sopenharmony_ci    /**
790e9297d28Sopenharmony_ci     * @brief Not-equal-to operator between sptr and a raw pointer.
791e9297d28Sopenharmony_ci     *
792e9297d28Sopenharmony_ci     * @param other Input raw pointer.
793e9297d28Sopenharmony_ci     * @return Return true if sptr does not point to the same object with input
794e9297d28Sopenharmony_ci     * raw pointer.
795e9297d28Sopenharmony_ci     */
796e9297d28Sopenharmony_ci    inline bool operator!=(const T *other) const
797e9297d28Sopenharmony_ci    {
798e9297d28Sopenharmony_ci        return !operator==(other);
799e9297d28Sopenharmony_ci    }
800e9297d28Sopenharmony_ci
801e9297d28Sopenharmony_ci    /**
802e9297d28Sopenharmony_ci     * @brief Equal-to operator between sptr and a wptr.
803e9297d28Sopenharmony_ci     *
804e9297d28Sopenharmony_ci     * @param other Input wptr.
805e9297d28Sopenharmony_ci     * @return Return true if sptr and wptr are managing same object.
806e9297d28Sopenharmony_ci     */
807e9297d28Sopenharmony_ci    bool operator==(const wptr<T> &other) const;
808e9297d28Sopenharmony_ci
809e9297d28Sopenharmony_ci    /**
810e9297d28Sopenharmony_ci     * @brief Not-equal-to operator between sptr and a wptr.
811e9297d28Sopenharmony_ci     *
812e9297d28Sopenharmony_ci     * @param other Input wptr.
813e9297d28Sopenharmony_ci     * @return Return true if sptr and wptr are not managing same object.
814e9297d28Sopenharmony_ci     */
815e9297d28Sopenharmony_ci    inline bool operator!=(const wptr<T> &other) const
816e9297d28Sopenharmony_ci    {
817e9297d28Sopenharmony_ci        return !operator==(other);
818e9297d28Sopenharmony_ci    }
819e9297d28Sopenharmony_ci
820e9297d28Sopenharmony_ci    /**
821e9297d28Sopenharmony_ci     * @brief Equal-to operator between sptrs.
822e9297d28Sopenharmony_ci     *
823e9297d28Sopenharmony_ci     * @param other Input sptr.
824e9297d28Sopenharmony_ci     * @return Return true if two sptrs are managing same object.
825e9297d28Sopenharmony_ci     */
826e9297d28Sopenharmony_ci    bool operator==(const sptr<T> &other) const;
827e9297d28Sopenharmony_ci
828e9297d28Sopenharmony_ci    /**
829e9297d28Sopenharmony_ci     * @brief Not-equal-to operator between sptrs.
830e9297d28Sopenharmony_ci     *
831e9297d28Sopenharmony_ci     * @param other Input sptr.
832e9297d28Sopenharmony_ci     * @return Return true if two sptrs are not managing same object.
833e9297d28Sopenharmony_ci     */
834e9297d28Sopenharmony_ci    inline bool operator!=(const sptr<T> &other) const
835e9297d28Sopenharmony_ci    {
836e9297d28Sopenharmony_ci        return !operator==(other);
837e9297d28Sopenharmony_ci    }
838e9297d28Sopenharmony_ci
839e9297d28Sopenharmony_ciprivate:
840e9297d28Sopenharmony_ci    T *refs_ = nullptr; // Raw pointer to the managed specific object
841e9297d28Sopenharmony_ci};
842e9297d28Sopenharmony_ci
843e9297d28Sopenharmony_citemplate <typename T>
844e9297d28Sopenharmony_ciinline void sptr<T>::ForceSetRefPtr(T *other)
845e9297d28Sopenharmony_ci{
846e9297d28Sopenharmony_ci    refs_ = other;
847e9297d28Sopenharmony_ci}
848e9297d28Sopenharmony_ci
849e9297d28Sopenharmony_citemplate <typename T>
850e9297d28Sopenharmony_ciinline sptr<T>::sptr()
851e9297d28Sopenharmony_ci{
852e9297d28Sopenharmony_ci    refs_ = nullptr;
853e9297d28Sopenharmony_ci}
854e9297d28Sopenharmony_ci
855e9297d28Sopenharmony_citemplate <typename T>
856e9297d28Sopenharmony_ciinline sptr<T>::sptr(T *other)
857e9297d28Sopenharmony_ci{
858e9297d28Sopenharmony_ci    refs_ = other;
859e9297d28Sopenharmony_ci    if (refs_ != nullptr) {
860e9297d28Sopenharmony_ci        refs_->IncStrongRef(this);
861e9297d28Sopenharmony_ci    }
862e9297d28Sopenharmony_ci}
863e9297d28Sopenharmony_ci
864e9297d28Sopenharmony_citemplate <typename T>
865e9297d28Sopenharmony_ciinline sptr<T>::sptr(const sptr<T> &other)
866e9297d28Sopenharmony_ci{
867e9297d28Sopenharmony_ci    refs_ = other.GetRefPtr();
868e9297d28Sopenharmony_ci    if (refs_ != nullptr) {
869e9297d28Sopenharmony_ci        refs_->IncStrongRef(this);
870e9297d28Sopenharmony_ci    }
871e9297d28Sopenharmony_ci}
872e9297d28Sopenharmony_ci
873e9297d28Sopenharmony_citemplate <typename T>
874e9297d28Sopenharmony_cisptr<T>::sptr(sptr<T> &&other)
875e9297d28Sopenharmony_ci{
876e9297d28Sopenharmony_ci    refs_ = other.GetRefPtr();
877e9297d28Sopenharmony_ci    other.ForceSetRefPtr(nullptr);
878e9297d28Sopenharmony_ci}
879e9297d28Sopenharmony_ci
880e9297d28Sopenharmony_citemplate <typename T>
881e9297d28Sopenharmony_cisptr<T> &sptr<T>::operator=(sptr<T> &&other)
882e9297d28Sopenharmony_ci{
883e9297d28Sopenharmony_ci    if (refs_ != nullptr) {
884e9297d28Sopenharmony_ci        refs_->DecStrongRef(this);
885e9297d28Sopenharmony_ci    }
886e9297d28Sopenharmony_ci    refs_ = other.GetRefPtr();
887e9297d28Sopenharmony_ci    other.ForceSetRefPtr(nullptr);
888e9297d28Sopenharmony_ci    return *this;
889e9297d28Sopenharmony_ci}
890e9297d28Sopenharmony_ci
891e9297d28Sopenharmony_citemplate <typename T>
892e9297d28Sopenharmony_citemplate <typename O>
893e9297d28Sopenharmony_cisptr<T>::sptr(const sptr<O> &other) : refs_(other.GetRefPtr())
894e9297d28Sopenharmony_ci{
895e9297d28Sopenharmony_ci    if (refs_ != nullptr) {
896e9297d28Sopenharmony_ci        refs_->IncStrongRef(this);
897e9297d28Sopenharmony_ci    }
898e9297d28Sopenharmony_ci}
899e9297d28Sopenharmony_ci
900e9297d28Sopenharmony_citemplate <typename T>
901e9297d28Sopenharmony_ciinline sptr<T> &sptr<T>::operator=(T *other)
902e9297d28Sopenharmony_ci{
903e9297d28Sopenharmony_ci    if (other != nullptr) {
904e9297d28Sopenharmony_ci        other->IncStrongRef(this);
905e9297d28Sopenharmony_ci    }
906e9297d28Sopenharmony_ci
907e9297d28Sopenharmony_ci    if (refs_ != nullptr) {
908e9297d28Sopenharmony_ci        refs_->DecStrongRef(this);
909e9297d28Sopenharmony_ci    }
910e9297d28Sopenharmony_ci
911e9297d28Sopenharmony_ci    refs_ = other;
912e9297d28Sopenharmony_ci    return *this;
913e9297d28Sopenharmony_ci}
914e9297d28Sopenharmony_ci
915e9297d28Sopenharmony_citemplate <typename T>
916e9297d28Sopenharmony_ciinline sptr<T> &sptr<T>::operator=(const sptr<T> &other)
917e9297d28Sopenharmony_ci{
918e9297d28Sopenharmony_ci    T *otherRef(other.GetRefPtr());
919e9297d28Sopenharmony_ci    if (otherRef != nullptr) {
920e9297d28Sopenharmony_ci        otherRef->IncStrongRef(this);
921e9297d28Sopenharmony_ci    }
922e9297d28Sopenharmony_ci
923e9297d28Sopenharmony_ci    if (refs_ != nullptr) {
924e9297d28Sopenharmony_ci        refs_->DecStrongRef(this);
925e9297d28Sopenharmony_ci    }
926e9297d28Sopenharmony_ci
927e9297d28Sopenharmony_ci    refs_ = otherRef;
928e9297d28Sopenharmony_ci    return *this;
929e9297d28Sopenharmony_ci}
930e9297d28Sopenharmony_ci
931e9297d28Sopenharmony_citemplate <typename T>
932e9297d28Sopenharmony_ciinline sptr<T> &sptr<T>::operator=(const wptr<T> &other)
933e9297d28Sopenharmony_ci{
934e9297d28Sopenharmony_ci    if (refs_ != nullptr) {
935e9297d28Sopenharmony_ci        refs_->DecStrongRef(this);
936e9297d28Sopenharmony_ci    }
937e9297d28Sopenharmony_ci    if ((other != nullptr) && other.AttemptIncStrongRef(this)) {
938e9297d28Sopenharmony_ci        refs_ = other.GetRefPtr();
939e9297d28Sopenharmony_ci    } else {
940e9297d28Sopenharmony_ci        refs_ = nullptr;
941e9297d28Sopenharmony_ci    }
942e9297d28Sopenharmony_ci
943e9297d28Sopenharmony_ci    return *this;
944e9297d28Sopenharmony_ci}
945e9297d28Sopenharmony_ci
946e9297d28Sopenharmony_citemplate <typename T>
947e9297d28Sopenharmony_citemplate <typename O>
948e9297d28Sopenharmony_cisptr<T> &sptr<T>::operator=(const sptr<O> &other)
949e9297d28Sopenharmony_ci{
950e9297d28Sopenharmony_ci    T *otherRef(other.GetRefPtr());
951e9297d28Sopenharmony_ci    if (otherRef != nullptr) {
952e9297d28Sopenharmony_ci        otherRef->IncStrongRef(this);
953e9297d28Sopenharmony_ci    }
954e9297d28Sopenharmony_ci
955e9297d28Sopenharmony_ci    if (refs_ != nullptr) {
956e9297d28Sopenharmony_ci        refs_->DecStrongRef(this);
957e9297d28Sopenharmony_ci    }
958e9297d28Sopenharmony_ci
959e9297d28Sopenharmony_ci    refs_ = otherRef;
960e9297d28Sopenharmony_ci    return *this;
961e9297d28Sopenharmony_ci}
962e9297d28Sopenharmony_ci
963e9297d28Sopenharmony_citemplate <typename T>
964e9297d28Sopenharmony_ciinline bool sptr<T>::operator==(const T *other) const
965e9297d28Sopenharmony_ci{
966e9297d28Sopenharmony_ci    return other == refs_;
967e9297d28Sopenharmony_ci}
968e9297d28Sopenharmony_ci
969e9297d28Sopenharmony_citemplate <typename T>
970e9297d28Sopenharmony_ciinline bool sptr<T>::operator==(const wptr<T> &other) const
971e9297d28Sopenharmony_ci{
972e9297d28Sopenharmony_ci    return refs_ == other.GetRefPtr();
973e9297d28Sopenharmony_ci}
974e9297d28Sopenharmony_ci
975e9297d28Sopenharmony_citemplate <typename T>
976e9297d28Sopenharmony_ciinline bool sptr<T>::operator==(const sptr<T> &other) const
977e9297d28Sopenharmony_ci{
978e9297d28Sopenharmony_ci    return refs_ == other.GetRefPtr();
979e9297d28Sopenharmony_ci}
980e9297d28Sopenharmony_ci
981e9297d28Sopenharmony_citemplate<typename T>
982e9297d28Sopenharmony_civoid sptr<T>::clear()
983e9297d28Sopenharmony_ci{
984e9297d28Sopenharmony_ci    if (refs_) {
985e9297d28Sopenharmony_ci        refs_->DecStrongRef(this);
986e9297d28Sopenharmony_ci        refs_ = 0;
987e9297d28Sopenharmony_ci    }
988e9297d28Sopenharmony_ci}
989e9297d28Sopenharmony_ci
990e9297d28Sopenharmony_citemplate <typename T>
991e9297d28Sopenharmony_ciinline sptr<T>::~sptr()
992e9297d28Sopenharmony_ci{
993e9297d28Sopenharmony_ci    if (refs_ != nullptr) {
994e9297d28Sopenharmony_ci        refs_->DecStrongRef(this);
995e9297d28Sopenharmony_ci    }
996e9297d28Sopenharmony_ci}
997e9297d28Sopenharmony_ci
998e9297d28Sopenharmony_citemplate <typename T>
999e9297d28Sopenharmony_ciinline sptr<T>::sptr(WeakRefCounter *p, bool /* force */)
1000e9297d28Sopenharmony_ci{
1001e9297d28Sopenharmony_ci    if ((p != nullptr) && p->AttemptIncStrongRef(this)) {
1002e9297d28Sopenharmony_ci        refs_ = reinterpret_cast<T *>(p->GetRefPtr());
1003e9297d28Sopenharmony_ci    } else {
1004e9297d28Sopenharmony_ci        refs_ = nullptr;
1005e9297d28Sopenharmony_ci    }
1006e9297d28Sopenharmony_ci}
1007e9297d28Sopenharmony_ci
1008e9297d28Sopenharmony_ci/**
1009e9297d28Sopenharmony_ci * @ingroup SmartPointer
1010e9297d28Sopenharmony_ci * @brief Weak reference smart pointer to a RefBase(or its subclass) object.
1011e9297d28Sopenharmony_ci *
1012e9297d28Sopenharmony_ci * Indirectly reference the RefBase object;
1013e9297d28Sopenharmony_ci * Directly reference the WeakRefCounter object.
1014e9297d28Sopenharmony_ci *
1015e9297d28Sopenharmony_ci * @tparam T Specific class type managed by wptr.
1016e9297d28Sopenharmony_ci * This class must inherit from RefBase.
1017e9297d28Sopenharmony_ci */
1018e9297d28Sopenharmony_citemplate <typename T>
1019e9297d28Sopenharmony_ciclass wptr {
1020e9297d28Sopenharmony_ci    template <typename O>
1021e9297d28Sopenharmony_ci    friend class wptr;
1022e9297d28Sopenharmony_ci
1023e9297d28Sopenharmony_cipublic:
1024e9297d28Sopenharmony_ci    wptr();
1025e9297d28Sopenharmony_ci
1026e9297d28Sopenharmony_ci    /**
1027e9297d28Sopenharmony_ci     * @brief Constructor with specified object to be managed.
1028e9297d28Sopenharmony_ci     *
1029e9297d28Sopenharmony_ci     * This method will create WeakRefCounter object for `other` and set its
1030e9297d28Sopenharmony_ci     * weak reference count to 1.
1031e9297d28Sopenharmony_ci     *
1032e9297d28Sopenharmony_ci     * @note WeakRefCounter object will not be created if `other` is a
1033e9297d28Sopenharmony_ci     * `nullptr`.
1034e9297d28Sopenharmony_ci     * @param other Object to be managed by wptr.
1035e9297d28Sopenharmony_ci     */
1036e9297d28Sopenharmony_ci    wptr(T *other);
1037e9297d28Sopenharmony_ci
1038e9297d28Sopenharmony_ci    /**
1039e9297d28Sopenharmony_ci     * @brief Copy constructor for wptr with same managed class type(T).
1040e9297d28Sopenharmony_ci     *
1041e9297d28Sopenharmony_ci     * This method will share the WeakRefCounter object of `other` with this
1042e9297d28Sopenharmony_ci     * wptr. Weak reference count in this WeakRefCounter object will be set
1043e9297d28Sopenharmony_ci     * properly.
1044e9297d28Sopenharmony_ci     *
1045e9297d28Sopenharmony_ci     * @param other Another wptr with same managed class type(T).
1046e9297d28Sopenharmony_ci     */
1047e9297d28Sopenharmony_ci    wptr(const wptr<T> &other);
1048e9297d28Sopenharmony_ci
1049e9297d28Sopenharmony_ci    /**
1050e9297d28Sopenharmony_ci     * @brief Copy constructor for sptr with same managed class type(T).
1051e9297d28Sopenharmony_ci     *
1052e9297d28Sopenharmony_ci     * This method will create WeakRefCounter object for the managed object of
1053e9297d28Sopenharmony_ci     * `other`, and set its weak reference count properly.
1054e9297d28Sopenharmony_ci     *
1055e9297d28Sopenharmony_ci     * @param other Another sptr with same managed class type(T).
1056e9297d28Sopenharmony_ci     * @tparam T Specific class type managed by `other`.
1057e9297d28Sopenharmony_ci     */
1058e9297d28Sopenharmony_ci    wptr(const sptr<T> &other);
1059e9297d28Sopenharmony_ci
1060e9297d28Sopenharmony_ci    /**
1061e9297d28Sopenharmony_ci     * @brief Copy constructor for wptr with different managed class type(O).
1062e9297d28Sopenharmony_ci     *
1063e9297d28Sopenharmony_ci     * Same with wptr<T>::wptr(const wptr<T> &other).
1064e9297d28Sopenharmony_ci     *
1065e9297d28Sopenharmony_ci     * @tparam O Class type managed by `other`.
1066e9297d28Sopenharmony_ci     * @param other Another wptr with different managed class type(O).
1067e9297d28Sopenharmony_ci     * @tparam T Specific class type managed by `other`.
1068e9297d28Sopenharmony_ci     */
1069e9297d28Sopenharmony_ci    template <typename O>
1070e9297d28Sopenharmony_ci    wptr(const wptr<O> &other);
1071e9297d28Sopenharmony_ci
1072e9297d28Sopenharmony_ci    /**
1073e9297d28Sopenharmony_ci     * @brief Copy constructor for sptr with different managed class type(O).
1074e9297d28Sopenharmony_ci     *
1075e9297d28Sopenharmony_ci     * Same with wptr<T>::wptr(const sptr<T> &other).
1076e9297d28Sopenharmony_ci     *
1077e9297d28Sopenharmony_ci     * @param other Another sptr with same managed class type(O).
1078e9297d28Sopenharmony_ci     * @tparam T Specific class type managed by `other`.
1079e9297d28Sopenharmony_ci     */
1080e9297d28Sopenharmony_ci    template <typename O>
1081e9297d28Sopenharmony_ci    wptr(const sptr<O> &other);
1082e9297d28Sopenharmony_ci
1083e9297d28Sopenharmony_ci    /**
1084e9297d28Sopenharmony_ci     * @brief Copy assignment operator with specified object to be managed.
1085e9297d28Sopenharmony_ci     *
1086e9297d28Sopenharmony_ci     * @note Current wptr will unbind the original WeakRefCounter object and
1087e9297d28Sopenharmony_ci     * create a new WeakRefCounter object, then set its weak reference count
1088e9297d28Sopenharmony_ci     * properly.
1089e9297d28Sopenharmony_ci     * @param other Another object to be managed by this wptr.
1090e9297d28Sopenharmony_ci     */
1091e9297d28Sopenharmony_ci    wptr<T> &operator=(T *other);
1092e9297d28Sopenharmony_ci
1093e9297d28Sopenharmony_ci    /**
1094e9297d28Sopenharmony_ci     * @brief Copy assignment operator with specified object to be managed.
1095e9297d28Sopenharmony_ci     *
1096e9297d28Sopenharmony_ci     * @note Same with wptr<T> &operator=(T *other), but a pointer type casting
1097e9297d28Sopenharmony_ci     * which will not affect the type of `*other` is proccessed.
1098e9297d28Sopenharmony_ci     * @tparam O Specific class type managed by `other`.
1099e9297d28Sopenharmony_ci     * @param other Another object to be managed by this wptr.
1100e9297d28Sopenharmony_ci     *
1101e9297d28Sopenharmony_ci     */
1102e9297d28Sopenharmony_ci    template <typename O>
1103e9297d28Sopenharmony_ci    wptr<T> &operator=(O *other);
1104e9297d28Sopenharmony_ci
1105e9297d28Sopenharmony_ci    /**
1106e9297d28Sopenharmony_ci     * @brief Copy assignment operator for wptr with same managed class type(T).
1107e9297d28Sopenharmony_ci     *
1108e9297d28Sopenharmony_ci     * @note Current wptr will unbind the original WeakRefCounter object and
1109e9297d28Sopenharmony_ci     * share the WeakRefCounter object with `other`, then set its weak
1110e9297d28Sopenharmony_ci     * reference count properly.
1111e9297d28Sopenharmony_ci     * @param other Another wptr. Object managed by it will also be managed by
1112e9297d28Sopenharmony_ci     * this wptr.
1113e9297d28Sopenharmony_ci     */
1114e9297d28Sopenharmony_ci    wptr<T> &operator=(const wptr<T> &other);
1115e9297d28Sopenharmony_ci
1116e9297d28Sopenharmony_ci    /**
1117e9297d28Sopenharmony_ci     * @brief Copy assignment operator for sptr with
1118e9297d28Sopenharmony_ci     * same managed class type(T).
1119e9297d28Sopenharmony_ci     *
1120e9297d28Sopenharmony_ci     * @note Current wptr will unbind the original WeakRefCounter object and
1121e9297d28Sopenharmony_ci     * create a new WeakRefCounter object, then set its weak reference count
1122e9297d28Sopenharmony_ci     * properly.
1123e9297d28Sopenharmony_ci     * @param other A sptr object. Object managed by it will also be managed by
1124e9297d28Sopenharmony_ci     * this wptr.
1125e9297d28Sopenharmony_ci     */
1126e9297d28Sopenharmony_ci    wptr<T> &operator=(const sptr<T> &other);
1127e9297d28Sopenharmony_ci
1128e9297d28Sopenharmony_ci    /**
1129e9297d28Sopenharmony_ci     * @brief Copy assignment operator for wptr with
1130e9297d28Sopenharmony_ci     * different managed class type(O).
1131e9297d28Sopenharmony_ci     *
1132e9297d28Sopenharmony_ci     * @note Same with wptr<T> &operator=(const wptr<T> &). Note that no cast
1133e9297d28Sopenharmony_ci     * here is proccessed.
1134e9297d28Sopenharmony_ci     * @param other An wptr object. Object managed by it will also be managed by
1135e9297d28Sopenharmony_ci     * this wptr.
1136e9297d28Sopenharmony_ci     * @tparam O Specific class type managed by `other`.
1137e9297d28Sopenharmony_ci     */
1138e9297d28Sopenharmony_ci    template <typename O>
1139e9297d28Sopenharmony_ci    wptr<T> &operator=(const wptr<O> &other);
1140e9297d28Sopenharmony_ci
1141e9297d28Sopenharmony_ci    /**
1142e9297d28Sopenharmony_ci     * @brief Copy assignment operator for sptr with
1143e9297d28Sopenharmony_ci     * different managed class type(O).
1144e9297d28Sopenharmony_ci     *
1145e9297d28Sopenharmony_ci     * @note Same with wptr<T> &wptr<T>::operator=(const sptr<T> &). Note that
1146e9297d28Sopenharmony_ci     * no cast here is proccessed.
1147e9297d28Sopenharmony_ci     * @param other An sptr object. Object managed by it will also be managed by
1148e9297d28Sopenharmony_ci     * this wptr.
1149e9297d28Sopenharmony_ci     * @tparam O Specific class type managed by `other`.
1150e9297d28Sopenharmony_ci     */
1151e9297d28Sopenharmony_ci    template <typename O>
1152e9297d28Sopenharmony_ci    wptr<T> &operator=(const sptr<O> &other);
1153e9297d28Sopenharmony_ci
1154e9297d28Sopenharmony_ci    /**
1155e9297d28Sopenharmony_ci     * @brief Dereference operator. It will return the object managed by this
1156e9297d28Sopenharmony_ci     * wptr.
1157e9297d28Sopenharmony_ci     *
1158e9297d28Sopenharmony_ci     * @return Return specific object managed by wptr.
1159e9297d28Sopenharmony_ci     */
1160e9297d28Sopenharmony_ci    inline T &operator*() const
1161e9297d28Sopenharmony_ci    {
1162e9297d28Sopenharmony_ci        return *GetRefPtr();
1163e9297d28Sopenharmony_ci    }
1164e9297d28Sopenharmony_ci
1165e9297d28Sopenharmony_ci    /**
1166e9297d28Sopenharmony_ci     * @brief Member selection operator.
1167e9297d28Sopenharmony_ci     *
1168e9297d28Sopenharmony_ci     * It will return the specified member of the object managed by this wptr.
1169e9297d28Sopenharmony_ci     */
1170e9297d28Sopenharmony_ci    inline T *operator->() const
1171e9297d28Sopenharmony_ci    {
1172e9297d28Sopenharmony_ci        return reinterpret_cast<T *>(refs_->GetRefPtr());
1173e9297d28Sopenharmony_ci    }
1174e9297d28Sopenharmony_ci
1175e9297d28Sopenharmony_ci    /**
1176e9297d28Sopenharmony_ci     * @brief Equal-to operator between wptr and a raw pointer.
1177e9297d28Sopenharmony_ci     *
1178e9297d28Sopenharmony_ci     * @param other Input raw pointer.
1179e9297d28Sopenharmony_ci     * @return Return true if two pointers have same value.
1180e9297d28Sopenharmony_ci     */
1181e9297d28Sopenharmony_ci    bool operator==(const T *other) const;
1182e9297d28Sopenharmony_ci
1183e9297d28Sopenharmony_ci    /**
1184e9297d28Sopenharmony_ci     * @brief Not-equal-to operator between wptr and a raw pointer.
1185e9297d28Sopenharmony_ci     *
1186e9297d28Sopenharmony_ci     * @param other Input raw pointer.
1187e9297d28Sopenharmony_ci     * @return Return true if two pointers have different value.
1188e9297d28Sopenharmony_ci     */
1189e9297d28Sopenharmony_ci    inline bool operator!=(const T *other) const
1190e9297d28Sopenharmony_ci    {
1191e9297d28Sopenharmony_ci        return !operator==(other);
1192e9297d28Sopenharmony_ci    };
1193e9297d28Sopenharmony_ci
1194e9297d28Sopenharmony_ci    /**
1195e9297d28Sopenharmony_ci     * @brief Equal-to operator between two wptrs.
1196e9297d28Sopenharmony_ci     *
1197e9297d28Sopenharmony_ci     * @param other Input reference of a wptr object.
1198e9297d28Sopenharmony_ci     * @return Return if two pointers have same value.
1199e9297d28Sopenharmony_ci     */
1200e9297d28Sopenharmony_ci    bool operator==(const wptr<T> &other) const;
1201e9297d28Sopenharmony_ci
1202e9297d28Sopenharmony_ci    /**
1203e9297d28Sopenharmony_ci     * @brief Not-equal-to operator between two wptrs.
1204e9297d28Sopenharmony_ci     *
1205e9297d28Sopenharmony_ci     * @param other Input reference of a wptr object.
1206e9297d28Sopenharmony_ci     * @return Return if two pointers have different value.
1207e9297d28Sopenharmony_ci     */
1208e9297d28Sopenharmony_ci    inline bool operator!=(const wptr<T> &other) const
1209e9297d28Sopenharmony_ci    {
1210e9297d28Sopenharmony_ci        return !operator==(other);
1211e9297d28Sopenharmony_ci    }
1212e9297d28Sopenharmony_ci
1213e9297d28Sopenharmony_ci    /**
1214e9297d28Sopenharmony_ci     * @brief Equal-to operator between wptr and a input sptr object.
1215e9297d28Sopenharmony_ci     *
1216e9297d28Sopenharmony_ci     * @param other Input reference of an sptr object.
1217e9297d28Sopenharmony_ci     * @return Comparison result.
1218e9297d28Sopenharmony_ci     */
1219e9297d28Sopenharmony_ci    bool operator==(const sptr<T> &other) const;
1220e9297d28Sopenharmony_ci
1221e9297d28Sopenharmony_ci    /**
1222e9297d28Sopenharmony_ci     * @brief Not-Equal-to operator between wptr and a input sptr object.
1223e9297d28Sopenharmony_ci     *
1224e9297d28Sopenharmony_ci     * @param other Input reference of an sptr object.
1225e9297d28Sopenharmony_ci     * @return Comparison result.
1226e9297d28Sopenharmony_ci     */
1227e9297d28Sopenharmony_ci    inline bool operator!=(const sptr<T> &other) const
1228e9297d28Sopenharmony_ci    {
1229e9297d28Sopenharmony_ci        return !operator==(other);
1230e9297d28Sopenharmony_ci    }
1231e9297d28Sopenharmony_ci
1232e9297d28Sopenharmony_ci    /**
1233e9297d28Sopenharmony_ci     * @brief Get the pointer to the RefBase object.
1234e9297d28Sopenharmony_ci     *
1235e9297d28Sopenharmony_ci     * @return Raw pointer to the RefBase object.
1236e9297d28Sopenharmony_ci     * @note Return `nullptr` if the managed object has been deallocated.
1237e9297d28Sopenharmony_ci     */
1238e9297d28Sopenharmony_ci    T *GetRefPtr() const;
1239e9297d28Sopenharmony_ci
1240e9297d28Sopenharmony_ci    /**
1241e9297d28Sopenharmony_ci     * @brief Get the count value of corresponding WeakRefCounter object.
1242e9297d28Sopenharmony_ci     *
1243e9297d28Sopenharmony_ci     * The value indicates how many wptrs share the same WeakRefCounter object.
1244e9297d28Sopenharmony_ci     *
1245e9297d28Sopenharmony_ci     * @return Value of the count.
1246e9297d28Sopenharmony_ci     * @note Only for test.
1247e9297d28Sopenharmony_ci     */
1248e9297d28Sopenharmony_ci    inline int GetWeakRefCount() const
1249e9297d28Sopenharmony_ci    {
1250e9297d28Sopenharmony_ci        return refs_->GetWeakRefCount();
1251e9297d28Sopenharmony_ci    }
1252e9297d28Sopenharmony_ci
1253e9297d28Sopenharmony_ci    /**
1254e9297d28Sopenharmony_ci     * @brief Attempt to increment the strong reference count of
1255e9297d28Sopenharmony_ci     * the managed object.
1256e9297d28Sopenharmony_ci     *
1257e9297d28Sopenharmony_ci     * @return Return true after a success increment.
1258e9297d28Sopenharmony_ci     * @note Avoid using it independently. Use `promote()`.
1259e9297d28Sopenharmony_ci     */
1260e9297d28Sopenharmony_ci    inline bool AttemptIncStrongRef(const void *objectId) const
1261e9297d28Sopenharmony_ci    {
1262e9297d28Sopenharmony_ci        return refs_->AttemptIncStrongRef(objectId);
1263e9297d28Sopenharmony_ci    }
1264e9297d28Sopenharmony_ci
1265e9297d28Sopenharmony_ci    /**
1266e9297d28Sopenharmony_ci     * @brief Promote a wptr to an sptr.
1267e9297d28Sopenharmony_ci     *
1268e9297d28Sopenharmony_ci     * It will create an sptr object based on
1269e9297d28Sopenharmony_ci     * object managed by this wptr.
1270e9297d28Sopenharmony_ci     *
1271e9297d28Sopenharmony_ci     * @note Original weak reference will be retained. Promote may fail,
1272e9297d28Sopenharmony_ci     * and then return a "null sptr".
1273e9297d28Sopenharmony_ci     */
1274e9297d28Sopenharmony_ci    const sptr<T> promote() const;
1275e9297d28Sopenharmony_ci
1276e9297d28Sopenharmony_ci    ~wptr();
1277e9297d28Sopenharmony_ci
1278e9297d28Sopenharmony_ciprivate:
1279e9297d28Sopenharmony_ci    WeakRefCounter *refs_ = nullptr; // Pointer to the corresponding weak reference counter object
1280e9297d28Sopenharmony_ci};
1281e9297d28Sopenharmony_ci
1282e9297d28Sopenharmony_citemplate <typename T>
1283e9297d28Sopenharmony_ciinline T *wptr<T>::GetRefPtr() const
1284e9297d28Sopenharmony_ci{
1285e9297d28Sopenharmony_ci    return (refs_ != nullptr) ? reinterpret_cast<T *>(refs_->GetRefPtr()) : nullptr;
1286e9297d28Sopenharmony_ci}
1287e9297d28Sopenharmony_ci
1288e9297d28Sopenharmony_citemplate <typename T>
1289e9297d28Sopenharmony_ciwptr<T>::wptr()
1290e9297d28Sopenharmony_ci{
1291e9297d28Sopenharmony_ci    refs_ = nullptr;
1292e9297d28Sopenharmony_ci}
1293e9297d28Sopenharmony_ci
1294e9297d28Sopenharmony_citemplate <typename T>
1295e9297d28Sopenharmony_ciwptr<T>::wptr(T *other)
1296e9297d28Sopenharmony_ci{
1297e9297d28Sopenharmony_ci    if (other != nullptr) {
1298e9297d28Sopenharmony_ci        refs_ = other->CreateWeakRef(other);
1299e9297d28Sopenharmony_ci        if (refs_ != nullptr) {
1300e9297d28Sopenharmony_ci            refs_->IncWeakRefCount(this);
1301e9297d28Sopenharmony_ci        }
1302e9297d28Sopenharmony_ci    } else {
1303e9297d28Sopenharmony_ci        refs_ = nullptr;
1304e9297d28Sopenharmony_ci    }
1305e9297d28Sopenharmony_ci}
1306e9297d28Sopenharmony_ci
1307e9297d28Sopenharmony_citemplate <typename T>
1308e9297d28Sopenharmony_ciwptr<T>::wptr(const wptr<T> &other)
1309e9297d28Sopenharmony_ci{
1310e9297d28Sopenharmony_ci    refs_ = other.refs_;
1311e9297d28Sopenharmony_ci    if (refs_ != nullptr) {
1312e9297d28Sopenharmony_ci        refs_->IncWeakRefCount(this);
1313e9297d28Sopenharmony_ci    }
1314e9297d28Sopenharmony_ci}
1315e9297d28Sopenharmony_ci
1316e9297d28Sopenharmony_citemplate <typename T>
1317e9297d28Sopenharmony_ciwptr<T>::wptr(const sptr<T> &other)
1318e9297d28Sopenharmony_ci{
1319e9297d28Sopenharmony_ci    if (other.GetRefPtr() != nullptr) {
1320e9297d28Sopenharmony_ci        refs_ = other->CreateWeakRef(other.GetRefPtr());
1321e9297d28Sopenharmony_ci        if (refs_ != nullptr) {
1322e9297d28Sopenharmony_ci            refs_->IncWeakRefCount(this);
1323e9297d28Sopenharmony_ci        }
1324e9297d28Sopenharmony_ci    }
1325e9297d28Sopenharmony_ci}
1326e9297d28Sopenharmony_ci
1327e9297d28Sopenharmony_citemplate <typename T>
1328e9297d28Sopenharmony_citemplate <typename O>
1329e9297d28Sopenharmony_ciwptr<T>::wptr(const wptr<O> &other)
1330e9297d28Sopenharmony_ci{
1331e9297d28Sopenharmony_ci    refs_ = other.refs_;
1332e9297d28Sopenharmony_ci    if (refs_ != nullptr) {
1333e9297d28Sopenharmony_ci        refs_->IncWeakRefCount(this);
1334e9297d28Sopenharmony_ci    }
1335e9297d28Sopenharmony_ci}
1336e9297d28Sopenharmony_ci
1337e9297d28Sopenharmony_citemplate <typename T>
1338e9297d28Sopenharmony_citemplate <typename O>
1339e9297d28Sopenharmony_ciwptr<T>::wptr(const sptr<O> &other)
1340e9297d28Sopenharmony_ci{
1341e9297d28Sopenharmony_ci    if (other.GetRefPtr() != nullptr) {
1342e9297d28Sopenharmony_ci        refs_ = other->CreateWeakRef(other.GetRefPtr());
1343e9297d28Sopenharmony_ci        if (refs_ != nullptr) {
1344e9297d28Sopenharmony_ci            refs_->IncWeakRefCount(this);
1345e9297d28Sopenharmony_ci        }
1346e9297d28Sopenharmony_ci    }
1347e9297d28Sopenharmony_ci}
1348e9297d28Sopenharmony_ci
1349e9297d28Sopenharmony_citemplate <typename T>
1350e9297d28Sopenharmony_ciwptr<T> &wptr<T>::operator=(T *other)
1351e9297d28Sopenharmony_ci{
1352e9297d28Sopenharmony_ci    WeakRefCounter *newWeakRef = nullptr;
1353e9297d28Sopenharmony_ci    if (other != nullptr) {
1354e9297d28Sopenharmony_ci        newWeakRef = other->CreateWeakRef(other);
1355e9297d28Sopenharmony_ci        if (newWeakRef != nullptr) {
1356e9297d28Sopenharmony_ci            newWeakRef->IncWeakRefCount(this);
1357e9297d28Sopenharmony_ci        }
1358e9297d28Sopenharmony_ci    }
1359e9297d28Sopenharmony_ci
1360e9297d28Sopenharmony_ci    if (refs_ != nullptr) {
1361e9297d28Sopenharmony_ci        refs_->DecWeakRefCount(this);
1362e9297d28Sopenharmony_ci    }
1363e9297d28Sopenharmony_ci
1364e9297d28Sopenharmony_ci    refs_ = newWeakRef;
1365e9297d28Sopenharmony_ci    return *this;
1366e9297d28Sopenharmony_ci}
1367e9297d28Sopenharmony_ci
1368e9297d28Sopenharmony_citemplate <typename T>
1369e9297d28Sopenharmony_citemplate <typename O>
1370e9297d28Sopenharmony_ciwptr<T> &wptr<T>::operator=(O *other)
1371e9297d28Sopenharmony_ci{
1372e9297d28Sopenharmony_ci    T *object = reinterpret_cast<T *>(other);
1373e9297d28Sopenharmony_ci    WeakRefCounter *newWeakRef = nullptr;
1374e9297d28Sopenharmony_ci    if (object != nullptr) {
1375e9297d28Sopenharmony_ci        newWeakRef = object->CreateWeakRef(object);
1376e9297d28Sopenharmony_ci        if (newWeakRef != nullptr) {
1377e9297d28Sopenharmony_ci            newWeakRef->IncWeakRefCount(this);
1378e9297d28Sopenharmony_ci        }
1379e9297d28Sopenharmony_ci    }
1380e9297d28Sopenharmony_ci
1381e9297d28Sopenharmony_ci    if (refs_ != nullptr) {
1382e9297d28Sopenharmony_ci        refs_->DecWeakRefCount(this);
1383e9297d28Sopenharmony_ci    }
1384e9297d28Sopenharmony_ci
1385e9297d28Sopenharmony_ci    refs_ = newWeakRef;
1386e9297d28Sopenharmony_ci    return *this;
1387e9297d28Sopenharmony_ci}
1388e9297d28Sopenharmony_ci
1389e9297d28Sopenharmony_citemplate <typename T>
1390e9297d28Sopenharmony_ciinline wptr<T> &wptr<T>::operator=(const wptr<T> &other)
1391e9297d28Sopenharmony_ci{
1392e9297d28Sopenharmony_ci    if (other.refs_ != nullptr) {
1393e9297d28Sopenharmony_ci        other.refs_->IncWeakRefCount(this);
1394e9297d28Sopenharmony_ci    }
1395e9297d28Sopenharmony_ci
1396e9297d28Sopenharmony_ci    if (refs_ != nullptr) {
1397e9297d28Sopenharmony_ci        refs_->DecWeakRefCount(this);
1398e9297d28Sopenharmony_ci    }
1399e9297d28Sopenharmony_ci
1400e9297d28Sopenharmony_ci    refs_ = other.refs_;
1401e9297d28Sopenharmony_ci    return *this;
1402e9297d28Sopenharmony_ci}
1403e9297d28Sopenharmony_ci
1404e9297d28Sopenharmony_citemplate <typename T>
1405e9297d28Sopenharmony_ciinline wptr<T> &wptr<T>::operator=(const sptr<T> &other)
1406e9297d28Sopenharmony_ci{
1407e9297d28Sopenharmony_ci    WeakRefCounter *newWeakRef = nullptr;
1408e9297d28Sopenharmony_ci    if (other.GetRefPtr() != nullptr) {
1409e9297d28Sopenharmony_ci        newWeakRef = other->CreateWeakRef(other.GetRefPtr());
1410e9297d28Sopenharmony_ci        if (newWeakRef != nullptr) {
1411e9297d28Sopenharmony_ci            newWeakRef->IncWeakRefCount(this);
1412e9297d28Sopenharmony_ci        }
1413e9297d28Sopenharmony_ci    }
1414e9297d28Sopenharmony_ci
1415e9297d28Sopenharmony_ci    if (refs_ != nullptr) {
1416e9297d28Sopenharmony_ci        refs_->DecWeakRefCount(this);
1417e9297d28Sopenharmony_ci    }
1418e9297d28Sopenharmony_ci
1419e9297d28Sopenharmony_ci    refs_ = newWeakRef;
1420e9297d28Sopenharmony_ci    return *this;
1421e9297d28Sopenharmony_ci}
1422e9297d28Sopenharmony_ci
1423e9297d28Sopenharmony_citemplate <typename T>
1424e9297d28Sopenharmony_citemplate <typename O>
1425e9297d28Sopenharmony_ciwptr<T> &wptr<T>::operator=(const wptr<O> &other)
1426e9297d28Sopenharmony_ci{
1427e9297d28Sopenharmony_ci    if (other.refs_ != nullptr) {
1428e9297d28Sopenharmony_ci        other.refs_->IncWeakRefCount(this);
1429e9297d28Sopenharmony_ci    }
1430e9297d28Sopenharmony_ci
1431e9297d28Sopenharmony_ci    if (refs_ != nullptr) {
1432e9297d28Sopenharmony_ci        refs_->DecWeakRefCount(this);
1433e9297d28Sopenharmony_ci    }
1434e9297d28Sopenharmony_ci
1435e9297d28Sopenharmony_ci    refs_ = other.refs_;
1436e9297d28Sopenharmony_ci    return *this;
1437e9297d28Sopenharmony_ci}
1438e9297d28Sopenharmony_ci
1439e9297d28Sopenharmony_citemplate <typename T>
1440e9297d28Sopenharmony_citemplate <typename O>
1441e9297d28Sopenharmony_ciwptr<T> &wptr<T>::operator=(const sptr<O> &other)
1442e9297d28Sopenharmony_ci{
1443e9297d28Sopenharmony_ci    WeakRefCounter *newWeakRef = nullptr;
1444e9297d28Sopenharmony_ci    if (other.GetRefPtr() != nullptr) {
1445e9297d28Sopenharmony_ci        newWeakRef = other->CreateWeakRef(other.GetRefPtr());
1446e9297d28Sopenharmony_ci        if (newWeakRef != nullptr) {
1447e9297d28Sopenharmony_ci            newWeakRef->IncWeakRefCount(this);
1448e9297d28Sopenharmony_ci        }
1449e9297d28Sopenharmony_ci    }
1450e9297d28Sopenharmony_ci
1451e9297d28Sopenharmony_ci    if (refs_ != nullptr) {
1452e9297d28Sopenharmony_ci        refs_->DecWeakRefCount(this);
1453e9297d28Sopenharmony_ci    }
1454e9297d28Sopenharmony_ci
1455e9297d28Sopenharmony_ci    refs_ = newWeakRef;
1456e9297d28Sopenharmony_ci    return *this;
1457e9297d28Sopenharmony_ci}
1458e9297d28Sopenharmony_ci
1459e9297d28Sopenharmony_citemplate <typename T>
1460e9297d28Sopenharmony_ciinline bool wptr<T>::operator==(const T *other) const
1461e9297d28Sopenharmony_ci{
1462e9297d28Sopenharmony_ci    return GetRefPtr() == other;
1463e9297d28Sopenharmony_ci}
1464e9297d28Sopenharmony_ci
1465e9297d28Sopenharmony_citemplate <typename T>
1466e9297d28Sopenharmony_ciinline bool wptr<T>::operator==(const wptr<T> &other) const
1467e9297d28Sopenharmony_ci{
1468e9297d28Sopenharmony_ci    return GetRefPtr() == other.GetRefPtr();
1469e9297d28Sopenharmony_ci}
1470e9297d28Sopenharmony_ci
1471e9297d28Sopenharmony_citemplate <typename T>
1472e9297d28Sopenharmony_ciinline bool wptr<T>::operator==(const sptr<T> &other) const
1473e9297d28Sopenharmony_ci{
1474e9297d28Sopenharmony_ci    return GetRefPtr() == other.GetRefPtr();
1475e9297d28Sopenharmony_ci}
1476e9297d28Sopenharmony_ci
1477e9297d28Sopenharmony_citemplate <typename T>
1478e9297d28Sopenharmony_ciinline const sptr<T> wptr<T>::promote() const
1479e9297d28Sopenharmony_ci{
1480e9297d28Sopenharmony_ci    return sptr<T>(refs_, true);
1481e9297d28Sopenharmony_ci}
1482e9297d28Sopenharmony_ci
1483e9297d28Sopenharmony_citemplate <typename T>
1484e9297d28Sopenharmony_ciinline wptr<T>::~wptr()
1485e9297d28Sopenharmony_ci{
1486e9297d28Sopenharmony_ci    if (refs_ != nullptr) {
1487e9297d28Sopenharmony_ci        refs_->DecWeakRefCount(this);
1488e9297d28Sopenharmony_ci    }
1489e9297d28Sopenharmony_ci}
1490e9297d28Sopenharmony_ci
1491e9297d28Sopenharmony_ci} // namespace OHOS
1492e9297d28Sopenharmony_ci
1493e9297d28Sopenharmony_ci#endif
1494e9297d28Sopenharmony_ci
1495e9297d28Sopenharmony_ci/**@}*/
1496