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