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