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