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