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