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