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