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