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