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