• 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 Constructor with the specified object to be managed.
597      *
598      * @note A null sptr will be created if `other` is `nullptr`.
599      * @param other Object to be managed by wptr.
600      */
601     sptr(T *other);
602 
603     /**
604      * @brief Copy constructor for sptr with the managed class type (T).
605      *
606      * @param other Input sptr object.
607      */
608     sptr(const sptr<T> &other);
609 
610     /**
611      * @brief Move constructor.
612      *
613      * @note `other` will be set to a null sptr.
614      * @param other Input sptr object.
615      */
616     sptr(sptr<T> &&other);
617 
618     /**
619      * @brief Move assignment operator.
620      *
621      * @param other Input sptr object.
622      * @note The original strong reference in target sptr object will
623      * be removed.
624      */
625     sptr<T> &operator=(sptr<T> &&other);
626 
627     /**
628      * @brief Copy Constructor for sptr with the managed class type (O).
629      *
630      * @tparam O Another specific class type managed by `other`.
631      * @param other Input sptr object.
632      */
633     template <typename O>
634     sptr(const sptr<O> &other);
635 
636     /**
637      * @brief Constructor used to promote the process of wptr.
638      *
639      * @param p WeakRefCounter object which hold the reference to the
640      * managed object.
641      * @param force Used to distinguish from other constructors.
642      */
643     inline sptr(WeakRefCounter *p, bool force);
644 
645     /**
646      * @brief Gets the pointer to the managed object.
647      *
648      * @return Pointer of the specific managed class type.
649      */
GetRefPtr()650     inline T *GetRefPtr() const
651     {
652         return refs_;
653     }
654 
655     /**
656      * @brief Sets the pointer to the managed object.
657      *
658      * @param other Another pointer object to be managed by sptr.
659      * @note Avoid using this function independently. Otherwise,
660      * a mismatch of the reference count will arise, leading to memory problems.
661      */
662     inline void ForceSetRefPtr(T *other);
663 
664     /**
665      * @brief Removes the reference to the managed object held by current sptr.
666      *
667      * @note This function will make this sptr a "null sptr".
668      */
669     void clear();
670 
671     /**
672      * @brief Type conversion operator.
673      *
674      * @return Raw pointer to the managed object.
675      * @note The sptr object will not be converted. Only the member raw
676      * pointer will be returned.
677      */
678     inline operator T *() const
679     {
680         return refs_;
681     }
682 
683     /**
684      * @brief Dereference operator.
685      *
686      * This function will return the object managed by this sptr.
687      *
688      * @return Reference to the specific object managed by sptr.
689      */
690     inline T &operator*() const
691     {
692         return *refs_;
693     }
694 
695     /**
696      * @brief Member selection operator.
697      *
698      * This function will return the specified member of the object
699      * managed by this sptr.
700      */
701     inline T *operator->() const
702     {
703         return refs_;
704     }
705 
706     /**
707      * @brief Logical-NOT operator, which is used to check if
708      * the sptr is a "null sptr".
709      *
710      * @return `true` if sptr is a "null sptr"; `false` otherwise.
711      */
712     inline bool operator!() const
713     {
714         return refs_ == nullptr;
715     }
716 
717     /**
718      * @brief Copy assignment operator with the specified object to be managed.
719      *
720      * @note The original reference will be removed, and a new reference to the
721      * input object will be established.
722      * @param other Another object to be managed by this sptr.
723      */
724     sptr<T> &operator=(T *other);
725 
726     /**
727      * @brief Copy assignment operator for sptr with
728      * the same managed class type (T).
729      *
730      * @note The original reference will be removed, and the same object
731      * with the input sptr object will be managed by this sptr.
732      * @param other Another sptr object with the same managed class type (T).
733      */
734     sptr<T> &operator=(const sptr<T> &other);
735 
736     /**
737      * @brief Copy assignment operator for wptr with
738      * the same managed class type (T).
739      *
740      * @note The original reference will be removed, and the same object
741      * with the input wptr object will be managed by this sptr.
742      * @note If the operation fails, this sptr will turn to be a "null sptr".
743      * @param other Another wptr object with the same managed class type (T).
744      */
745     sptr<T> &operator=(const wptr<T> &other);
746 
747     /**
748      * @brief Copy assignment operator for sptr with
749      * a different managed class type (O).
750      *
751      * @note The original reference will be removed, and the same object
752      * with the input sptr object will be managed by this sptr.
753      * @note This sptr will interpret the managed object as the type (T).
754      * @param other Another sptr object with a different managed class type (O).
755      */
756     template <typename O>
757     sptr<T> &operator=(const sptr<O> &other);
758 
759     /**
760      * @brief Equal-to operator between the sptr and raw pointer.
761      *
762      * @param other Input raw pointer.
763      * @return `true` if the sptr points to the same object with input
764      * raw pointer; `false` otherwise.
765      */
766     bool operator==(const T *other) const;
767 
768     /**
769      * @brief Not-equal-to operator between the sptr and raw pointer.
770      *
771      * @param other Input raw pointer.
772      * @return `true` if the sptr does not point to the same object
773      * with input raw pointer; `false` otherwise.
774      */
775     inline bool operator!=(const T *other) const
776     {
777         return !operator==(other);
778     }
779 
780     /**
781      * @brief Equal-to operator between the sptr and wptr.
782      *
783      * @param other Input wptr.
784      * @return `true` if the same object is managed by the sptr and wptr;
785      * `false` otherwise.
786      */
787     bool operator==(const wptr<T> &other) const;
788 
789     /**
790      * @brief Not-equal-to operator between the sptr and wptr.
791      *
792      * @param other Input wptr.
793      * @return `true` if different objects are managed by the sptr and wptr;
794      * `false` otherwise.
795      */
796     inline bool operator!=(const wptr<T> &other) const
797     {
798         return !operator==(other);
799     }
800 
801     /**
802      * @brief Equal-to operator between two sptrs.
803      *
804      * @param other Input sptr.
805      * @return `true` if the same object is managed by two sptrs;
806      * `false` otherwise.
807      */
808     bool operator==(const sptr<T> &other) const;
809 
810     /**
811      * @brief Not-equal-to operator between sptrs.
812      *
813      * @param other Input sptr.
814      * @return `true` if different objects are managed by two sptrs;
815      * `false` otherwise.
816      */
817     inline bool operator!=(const sptr<T> &other) const
818     {
819         return !operator==(other);
820     }
821 
822 private:
823     T *refs_ = nullptr; // Raw pointer to the specific managed object
824 };
825 
826 template <typename T>
ForceSetRefPtr(T * other)827 inline void sptr<T>::ForceSetRefPtr(T *other)
828 {
829     refs_ = other;
830 }
831 
832 template <typename T>
sptr()833 inline sptr<T>::sptr()
834 {
835     refs_ = nullptr;
836 }
837 
838 template <typename T>
sptr(T * other)839 inline sptr<T>::sptr(T *other)
840 {
841     refs_ = other;
842     if (refs_ != nullptr) {
843         refs_->IncStrongRef(this);
844     }
845 }
846 
847 template <typename T>
sptr(const sptr<T> & other)848 inline sptr<T>::sptr(const sptr<T> &other)
849 {
850     refs_ = other.GetRefPtr();
851     if (refs_ != nullptr) {
852         refs_->IncStrongRef(this);
853     }
854 }
855 
856 template <typename T>
sptr(sptr<T> && other)857 sptr<T>::sptr(sptr<T> &&other)
858 {
859     refs_ = other.GetRefPtr();
860     other.ForceSetRefPtr(nullptr);
861 }
862 
863 template <typename T>
864 sptr<T> &sptr<T>::operator=(sptr<T> &&other)
865 {
866     if (refs_ != nullptr) {
867         refs_->DecStrongRef(this);
868     }
869     refs_ = other.GetRefPtr();
870     other.ForceSetRefPtr(nullptr);
871     return *this;
872 }
873 
874 template <typename T>
875 template <typename O>
sptr(const sptr<O> & other)876 sptr<T>::sptr(const sptr<O> &other) : refs_(other.GetRefPtr())
877 {
878     if (refs_ != nullptr) {
879         refs_->IncStrongRef(this);
880     }
881 }
882 
883 template <typename T>
884 inline sptr<T> &sptr<T>::operator=(T *other)
885 {
886     if (other != nullptr) {
887         other->IncStrongRef(this);
888     }
889 
890     if (refs_ != nullptr) {
891         refs_->DecStrongRef(this);
892     }
893 
894     refs_ = other;
895     return *this;
896 }
897 
898 template <typename T>
899 inline sptr<T> &sptr<T>::operator=(const sptr<T> &other)
900 {
901     T *otherRef(other.GetRefPtr());
902     if (otherRef != nullptr) {
903         otherRef->IncStrongRef(this);
904     }
905 
906     if (refs_ != nullptr) {
907         refs_->DecStrongRef(this);
908     }
909 
910     refs_ = otherRef;
911     return *this;
912 }
913 
914 template <typename T>
915 inline sptr<T> &sptr<T>::operator=(const wptr<T> &other)
916 {
917     if (refs_ != nullptr) {
918         refs_->DecStrongRef(this);
919     }
920     if ((other != nullptr) && other.AttemptIncStrongRef(this)) {
921         refs_ = other.GetRefPtr();
922     } else {
923         refs_ = nullptr;
924     }
925 
926     return *this;
927 }
928 
929 template <typename T>
930 template <typename O>
931 sptr<T> &sptr<T>::operator=(const sptr<O> &other)
932 {
933     T *otherRef(other.GetRefPtr());
934     if (otherRef != nullptr) {
935         otherRef->IncStrongRef(this);
936     }
937 
938     if (refs_ != nullptr) {
939         refs_->DecStrongRef(this);
940     }
941 
942     refs_ = otherRef;
943     return *this;
944 }
945 
946 template <typename T>
947 inline bool sptr<T>::operator==(const T *other) const
948 {
949     return other == refs_;
950 }
951 
952 template <typename T>
953 inline bool sptr<T>::operator==(const wptr<T> &other) const
954 {
955     return refs_ == other.GetRefPtr();
956 }
957 
958 template <typename T>
959 inline bool sptr<T>::operator==(const sptr<T> &other) const
960 {
961     return refs_ == other.GetRefPtr();
962 }
963 
964 template<typename T>
clear()965 void sptr<T>::clear()
966 {
967     if (refs_) {
968         refs_->DecStrongRef(this);
969         refs_ = 0;
970     }
971 }
972 
973 template <typename T>
~sptr()974 inline sptr<T>::~sptr()
975 {
976     if (refs_ != nullptr) {
977         refs_->DecStrongRef(this);
978     }
979 }
980 
981 template <typename T>
sptr(WeakRefCounter * p,bool)982 inline sptr<T>::sptr(WeakRefCounter *p, bool /* force */)
983 {
984     if ((p != nullptr) && p->AttemptIncStrongRef(this)) {
985         refs_ = reinterpret_cast<T *>(p->GetRefPtr());
986     } else {
987         refs_ = nullptr;
988     }
989 }
990 
991 /**
992  * @ingroup SmartPointer
993  * @brief Weak reference smart pointer to a RefBase object
994  * (or an object of its subclass).
995  *
996  * A weak reference indirectly references the RefBase object
997  * and directly references the WeakRefCounter object.
998  *
999  * @tparam T Specific class type managed by wptr.
1000  * This class must inherit from RefBase.
1001  */
1002 template <typename T>
1003 class wptr {
1004     template <typename O>
1005     friend class wptr;
1006 
1007 public:
1008     wptr();
1009 
1010     /**
1011      * @brief Constructor with the specified object to be managed.
1012      *
1013      * This function will create WeakRefCounter object for `other`
1014      * and set the count of weak references to 1.
1015      *
1016      * @note A WeakRefCounter object will not be created if `other`
1017      * is a `nullptr`.
1018      *
1019      * @param other Object to be managed by wptr.
1020      */
1021     wptr(T *other);
1022 
1023     /**
1024      * @brief Copy constructor for wptr with the same managed class type (T).
1025      *
1026      * This function will share the WeakRefCounter object of `other` with this
1027      * wptr and set the count of weak references properly.
1028      *
1029      * @param other Another wptr with the same managed class type (T).
1030      */
1031     wptr(const wptr<T> &other);
1032 
1033     /**
1034      * @brief Copy constructor for sptr with the same managed class type (T).
1035      *
1036      * This function will create a WeakRefCounter object for the managed
1037      * object of `other`, and set the count of weak references properly.
1038      *
1039      * @param other Another sptr with the same managed class type (T).
1040      * @tparam T Specific class type managed by `other`.
1041      */
1042     wptr(const sptr<T> &other);
1043 
1044     /**
1045      * @brief Copy constructor for wptr with a different managed class type (O).
1046      *
1047      * This function is the same as wptr<T>::wptr(const wptr<T> &other).
1048      *
1049      * @tparam O Class type managed by `other`.
1050      * @param other Another wptr with a different managed class type (O).
1051      * @tparam T Specific class type managed by `other`.
1052      */
1053     template <typename O>
1054     wptr(const wptr<O> &other);
1055 
1056     /**
1057      * @brief Copy constructor for sptr with a different managed class type (O).
1058      *
1059      * This function is the same as wptr<T>::wptr(const sptr<T> &other).
1060      *
1061      * @param other Another sptr with the same managed class type (O).
1062      * @tparam T Specific class type managed by `other`.
1063      */
1064     template <typename O>
1065     wptr(const sptr<O> &other);
1066 
1067     /**
1068      * @brief Copy assignment operator with the specified object to be managed.
1069      *
1070      * @note The current wptr will unbind the original WeakRefCounter object,
1071      * create a new WeakRefCounter object, and then set the count of weak
1072      * references properly.
1073      * @param other Another object to be managed by this wptr.
1074      */
1075     wptr<T> &operator=(T *other);
1076 
1077     /**
1078      * @brief Copy assignment operator with the specified object to be managed.
1079      *
1080      * @note Same with wptr<T> &operator=(T *other), but a pointer type casting
1081      * which will not affect the type of `*other` is processed.
1082      * @tparam O Specific class type managed by `other`.
1083      * @param other Another object to be managed by this wptr.
1084      *
1085      */
1086     template <typename O>
1087     wptr<T> &operator=(O *other);
1088 
1089     /**
1090      * @brief Copy assignment operator for wptr with the same managed class
1091      * type (T).
1092      *
1093      * @note The current wptr will unbind the original WeakRefCounter object,
1094      * share the WeakRefCounter object with `other`, and then set the count of
1095      * weak references properly.
1096      * @param other Another wptr object. Objects managed by it will also be
1097      * managed by this wptr.
1098      */
1099     wptr<T> &operator=(const wptr<T> &other);
1100 
1101     /**
1102      * @brief Copy assignment operator for sptr with the same managed class
1103      * type (T).
1104      *
1105      * @note The current wptr will unbind the original WeakRefCounter object,
1106      * create a new WeakRefCounter object, and then set the count of weak
1107      * references properly.
1108      * @param other A sptr object. Objects managed by it will also be
1109      * managed by this wptr.
1110      */
1111     wptr<T> &operator=(const sptr<T> &other);
1112 
1113     /**
1114      * @brief Copy assignment operator for wptr with a different managed class
1115      * type (O).
1116      *
1117      * @note This function is the same as wptr<T> &operator=(const wptr<T> &).
1118      * Note that no cast here is processed.
1119      * @param other An wptr object. Objects managed by it will also be
1120      * managed by this wptr.
1121      * @tparam O Specific class type managed by `other`.
1122      */
1123     template <typename O>
1124     wptr<T> &operator=(const wptr<O> &other);
1125 
1126     /**
1127      * @brief Copy assignment operator for sptr with a different managed class
1128      * type (O).
1129      *
1130      * @note This function is the same as
1131      * wptr<T> &wptr<T>::operator=(const sptr<T> &).
1132      * Note that no cast here is processed.
1133      * @param other An sptr object. Objects managed by it will also be
1134      * managed by this wptr.
1135      * @tparam O Specific class type managed by `other`.
1136      */
1137     template <typename O>
1138     wptr<T> &operator=(const sptr<O> &other);
1139 
1140     /**
1141      * @brief Dereference operator.
1142      *
1143      * This function will return the object managed by this wptr.
1144      *
1145      * @return Specific object managed by wptr.
1146      */
1147     inline T &operator*() const
1148     {
1149         return *GetRefPtr();
1150     }
1151 
1152     /**
1153      * @brief Member selection operator.
1154      *
1155      * This function will return the specified object member managed
1156      * by this wptr.
1157      */
1158     inline T *operator->() const
1159     {
1160         return reinterpret_cast<T *>(refs_->GetRefPtr());
1161     }
1162 
1163     /**
1164      * @brief Equal-to operator between the wptr and raw pointer.
1165      *
1166      * @param other Input raw pointer.
1167      * @return `true` if two pointers have the same value; `false` otherwise.
1168      */
1169     bool operator==(const T *other) const;
1170 
1171     /**
1172      * @brief Not-equal-to operator between the wptr and raw pointer.
1173      *
1174      * @param other Input raw pointer.
1175      * @return `true` if two pointers have different values; `false` otherwise.
1176      */
1177     inline bool operator!=(const T *other) const
1178     {
1179         return !operator==(other);
1180     };
1181 
1182     /**
1183      * @brief Equal-to operator between two wptrs.
1184      *
1185      * @param other Input reference to a wptr object.
1186      * @return `true` if two pointers have the same value; `false` otherwise.
1187      */
1188     bool operator==(const wptr<T> &other) const;
1189 
1190     /**
1191      * @brief Not-equal-to operator between two wptrs.
1192      *
1193      * @param other Input reference to a wptr object.
1194      * @return `true` if two pointers have different values; `false` otherwise.
1195      */
1196     inline bool operator!=(const wptr<T> &other) const
1197     {
1198         return !operator==(other);
1199     }
1200 
1201     /**
1202      * @brief Equal-to operator between the wptr and input sptr object.
1203      *
1204      * @param other Input reference to an sptr object.
1205      * @return true` if two pointers have the same value; `false` otherwise.
1206      */
1207     bool operator==(const sptr<T> &other) const;
1208 
1209     /**
1210      * @brief Not-equal-to operator between the wptr and input sptr object.
1211      *
1212      * @param other Input reference to an sptr object.
1213      * @return `true` if two pointers have different values; `false` otherwise.
1214      */
1215     inline bool operator!=(const sptr<T> &other) const
1216     {
1217         return !operator==(other);
1218     }
1219 
1220     /**
1221      * @brief Gets the pointer to the RefBase object.
1222      *
1223      * @return Raw pointer to the RefBase object.
1224      * @note `nullptr` will be returned if the managed object has been
1225      * deallocated.
1226      */
1227     T *GetRefPtr() const;
1228 
1229     /**
1230      * @brief Gets the count of weak references in a WeakRefCounter object.
1231      *
1232      * The value indicates how many wptrs share the same WeakRefCounter object.
1233      *
1234      * @return Count of weak references.
1235      * @note Only for test.
1236      */
GetWeakRefCount()1237     inline int GetWeakRefCount() const
1238     {
1239         return refs_->GetWeakRefCount();
1240     }
1241 
1242     /**
1243      * @brief Attempts to increment the count of strong references in
1244      * the managed object.
1245      *
1246      * @return `true` if the increment is successful; `false` otherwise.
1247      * @note Avoid using this function independently. Use `promote()` instead.
1248      */
AttemptIncStrongRef(const void * objectId)1249     inline bool AttemptIncStrongRef(const void *objectId) const
1250     {
1251         return refs_->AttemptIncStrongRef(objectId);
1252     }
1253 
1254     /**
1255      * @brief Promotes a wptr to an sptr.
1256      *
1257      * This function will create an sptr object based on the object
1258      * managed by this wptr.
1259      *
1260      * @note The original weak reference will be retained.
1261      * If the promotion fails, a "null sptr" will be returned.
1262      */
1263     const sptr<T> promote() const;
1264 
1265     ~wptr();
1266 
1267 private:
1268     WeakRefCounter *refs_ = nullptr; // Pointer to the corresponding WeakRefCounter object
1269 };
1270 
1271 template <typename T>
GetRefPtr()1272 inline T *wptr<T>::GetRefPtr() const
1273 {
1274     return (refs_ != nullptr) ? reinterpret_cast<T *>(refs_->GetRefPtr()) : nullptr;
1275 }
1276 
1277 template <typename T>
wptr()1278 wptr<T>::wptr()
1279 {
1280     refs_ = nullptr;
1281 }
1282 
1283 template <typename T>
wptr(T * other)1284 wptr<T>::wptr(T *other)
1285 {
1286     if (other != nullptr) {
1287         refs_ = other->CreateWeakRef(other);
1288         if (refs_ != nullptr) {
1289             refs_->IncWeakRefCount(this);
1290         }
1291     } else {
1292         refs_ = nullptr;
1293     }
1294 }
1295 
1296 template <typename T>
wptr(const wptr<T> & other)1297 wptr<T>::wptr(const wptr<T> &other)
1298 {
1299     refs_ = other.refs_;
1300     if (refs_ != nullptr) {
1301         refs_->IncWeakRefCount(this);
1302     }
1303 }
1304 
1305 template <typename T>
wptr(const sptr<T> & other)1306 wptr<T>::wptr(const sptr<T> &other)
1307 {
1308     if (other.GetRefPtr() != nullptr) {
1309         refs_ = other->CreateWeakRef(other.GetRefPtr());
1310         if (refs_ != nullptr) {
1311             refs_->IncWeakRefCount(this);
1312         }
1313     }
1314 }
1315 
1316 template <typename T>
1317 template <typename O>
wptr(const wptr<O> & other)1318 wptr<T>::wptr(const wptr<O> &other)
1319 {
1320     refs_ = other.refs_;
1321     if (refs_ != nullptr) {
1322         refs_->IncWeakRefCount(this);
1323     }
1324 }
1325 
1326 template <typename T>
1327 template <typename O>
wptr(const sptr<O> & other)1328 wptr<T>::wptr(const sptr<O> &other)
1329 {
1330     if (other.GetRefPtr() != nullptr) {
1331         refs_ = other->CreateWeakRef(other.GetRefPtr());
1332         if (refs_ != nullptr) {
1333             refs_->IncWeakRefCount(this);
1334         }
1335     }
1336 }
1337 
1338 template <typename T>
1339 wptr<T> &wptr<T>::operator=(T *other)
1340 {
1341     WeakRefCounter *newWeakRef = nullptr;
1342     if (other != nullptr) {
1343         newWeakRef = other->CreateWeakRef(other);
1344         if (newWeakRef != nullptr) {
1345             newWeakRef->IncWeakRefCount(this);
1346         }
1347     }
1348 
1349     if (refs_ != nullptr) {
1350         refs_->DecWeakRefCount(this);
1351     }
1352 
1353     refs_ = newWeakRef;
1354     return *this;
1355 }
1356 
1357 template <typename T>
1358 template <typename O>
1359 wptr<T> &wptr<T>::operator=(O *other)
1360 {
1361     T *object = reinterpret_cast<T *>(other);
1362     WeakRefCounter *newWeakRef = nullptr;
1363     if (object != nullptr) {
1364         newWeakRef = object->CreateWeakRef(object);
1365         if (newWeakRef != nullptr) {
1366             newWeakRef->IncWeakRefCount(this);
1367         }
1368     }
1369 
1370     if (refs_ != nullptr) {
1371         refs_->DecWeakRefCount(this);
1372     }
1373 
1374     refs_ = newWeakRef;
1375     return *this;
1376 }
1377 
1378 template <typename T>
1379 inline wptr<T> &wptr<T>::operator=(const wptr<T> &other)
1380 {
1381     if (other.refs_ != nullptr) {
1382         other.refs_->IncWeakRefCount(this);
1383     }
1384 
1385     if (refs_ != nullptr) {
1386         refs_->DecWeakRefCount(this);
1387     }
1388 
1389     refs_ = other.refs_;
1390     return *this;
1391 }
1392 
1393 template <typename T>
1394 inline wptr<T> &wptr<T>::operator=(const sptr<T> &other)
1395 {
1396     WeakRefCounter *newWeakRef = nullptr;
1397     if (other.GetRefPtr() != nullptr) {
1398         newWeakRef = other->CreateWeakRef(other.GetRefPtr());
1399         if (newWeakRef != nullptr) {
1400             newWeakRef->IncWeakRefCount(this);
1401         }
1402     }
1403 
1404     if (refs_ != nullptr) {
1405         refs_->DecWeakRefCount(this);
1406     }
1407 
1408     refs_ = newWeakRef;
1409     return *this;
1410 }
1411 
1412 template <typename T>
1413 template <typename O>
1414 wptr<T> &wptr<T>::operator=(const wptr<O> &other)
1415 {
1416     if (other.refs_ != nullptr) {
1417         other.refs_->IncWeakRefCount(this);
1418     }
1419 
1420     if (refs_ != nullptr) {
1421         refs_->DecWeakRefCount(this);
1422     }
1423 
1424     refs_ = other.refs_;
1425     return *this;
1426 }
1427 
1428 template <typename T>
1429 template <typename O>
1430 wptr<T> &wptr<T>::operator=(const sptr<O> &other)
1431 {
1432     WeakRefCounter *newWeakRef = nullptr;
1433     if (other.GetRefPtr() != nullptr) {
1434         newWeakRef = other->CreateWeakRef(other.GetRefPtr());
1435         if (newWeakRef != nullptr) {
1436             newWeakRef->IncWeakRefCount(this);
1437         }
1438     }
1439 
1440     if (refs_ != nullptr) {
1441         refs_->DecWeakRefCount(this);
1442     }
1443 
1444     refs_ = newWeakRef;
1445     return *this;
1446 }
1447 
1448 template <typename T>
1449 inline bool wptr<T>::operator==(const T *other) const
1450 {
1451     return GetRefPtr() == other;
1452 }
1453 
1454 template <typename T>
1455 inline bool wptr<T>::operator==(const wptr<T> &other) const
1456 {
1457     return GetRefPtr() == other.GetRefPtr();
1458 }
1459 
1460 template <typename T>
1461 inline bool wptr<T>::operator==(const sptr<T> &other) const
1462 {
1463     return GetRefPtr() == other.GetRefPtr();
1464 }
1465 
1466 template <typename T>
promote()1467 inline const sptr<T> wptr<T>::promote() const
1468 {
1469     return sptr<T>(refs_, true);
1470 }
1471 
1472 template <typename T>
~wptr()1473 inline wptr<T>::~wptr()
1474 {
1475     if (refs_ != nullptr) {
1476         refs_->DecWeakRefCount(this);
1477     }
1478 }
1479 
1480 } // namespace OHOS
1481 
1482 #endif
1483 
1484 /**@}*/
1485