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