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 #ifndef EMULATOR_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 private:
261 void DebugRefBase(const void *objectId);
262
263 std::atomic<int> atomicStrong_; // = (num of sptr) or Initial-value
264 std::atomic<int> atomicWeak_; // = (num of sptr)+(num of WeakRefCounter)
265 std::atomic<int> atomicRefCount_; // = (num of WeakRefCounter) + 1
266 std::atomic<unsigned int> atomicFlags_; // Life-time extended flag
267 std::atomic<int> atomicAttempt_; // Number of attempts
268 RefPtrCallback callback_ = nullptr; // Callback function to deallocate the corresponding RefBase object
269 static constexpr unsigned int FLAG_EXTEND_LIFE_TIME = 0x00000002; // Extended life-time bit to be set via logic-OR
270 #ifndef EMULATOR_PLATFORM
271 CanPromote canPromote_ = nullptr;
272 #endif
273 #ifdef DEBUG_REFBASE
274 #ifdef TRACK_ALL
275 bool enableTrack = true;
276 #else
277 bool enableTrack = false;
278 #endif
279 std::mutex trackerMutex; // To ensure refTracker be thread-safe
280 #ifdef PRINT_TRACK_AT_ONCE
281 void PrintRefs(const void* objectId);
282 #else
283 RefTracker* refTracker = nullptr;
284 void GetNewTrace(const void* objectId);
285 void PrintTracker();
286 #endif
287 #endif
288 };
289
290 /**
291 * @ingroup SmartPointer
292 * @brief An intermediate class to represent the weak reference
293 * to the correspond RefBase object.
294 *
295 * A WeakRefCounter object can be shared by multiple wptr objects.\n
296 * It holds the references to the corresponding RefBase and RefCounter object.
297 * Those two references will be set as `nullptr` when the weak referenced
298 * target and its RefCounter object are deallocated. The WeakRefCounter
299 * object can remain alive even if the referenced target is deallocated.
300 */
301 class WeakRefCounter {
302 public:
303 /**
304 * @brief Constructs a WeakRefCounter object.
305 *
306 * @param counter Pointer to corresponding RefCounter object.
307 * @param cookie Pointer to corresponding RefBase object.
308 */
309 WeakRefCounter(RefCounter *counter, void *cookie);
310
311 virtual ~WeakRefCounter();
312
313 /**
314 * @brief Gets the current pointer to the corresponding RefBase object.
315 *
316 * @return A void pointer to the RefBase object.
317 * If the corresponding object is not alive, a `nullptr` will be returned.
318 * @note A void pointer means that you should cast it to the real type,
319 * since it can be any subclass of RefBase.
320 */
321 void *GetRefPtr();
322
323 /**
324 * @brief Increments the count of references to this WeakRefCounter object.
325 *
326 * @note This count is different from the count of weak references
327 * in RefCounter. It is equal to the count of wptrs directly
328 * referenced to this WeakRefCount object.
329 * @see RefCounter
330 */
331 void IncWeakRefCount(const void *objectId);
332
333 /**
334 * @brief Decrements the count of references to this WeakRefCounter object.
335 *
336 * @note This WeakRefCounter object will be deallocated when this count
337 * reaches 0.
338 */
339 void DecWeakRefCount(const void *objectId);
340
341 /**
342 * @brief Gets the count recorded by this WeakRefCounter object.
343 *
344 * @return Count recorded by this WeakRefCounter object.
345 * @note The count is different from that in RefCounter.
346 * @see RefCounter::GetWeakRefCount()
347 */
348 int GetWeakRefCount() const;
349
350 /**
351 * @brief Attempts to increment the count of strong references to
352 * the corresponding RefBase object (to promote a wptr to a sptr).
353 *
354 * @return `true` after a success increment.
355 */
356 bool AttemptIncStrongRef(const void *objectId);
357
358 private:
359 std::atomic<int> atomicWeak_; // Count of references to this
360 // WeakRefCounter object
361 // The value is equal to the count of wptrs
362 // that references this WeakRefCounter object.
363 RefCounter *refCounter_ = nullptr; // Reference to the RefCounter object of
364 // the corresponding RefBase object
365 void *cookie_ = nullptr; // Pointer to the corresponding RefBase object
366 };
367
368 /**
369 * @ingroup SmartPointer
370 * @brief A base class of subclasses that can be managed by SmartPointer.
371 *
372 * @note All classes which intend to be managed by SmartPointer should be
373 * derived from RefBase.
374 */
375 class RefBase {
376 public:
377 RefBase();
378
379 /**
380 * @brief Copy constructor of RefBase.
381 *
382 * @note This function constructs a new RefCounter object
383 * and binds it to the RefBase object.
384 */
385 RefBase(const RefBase &);
386
387 /**
388 * @brief Copy assignment operator of RefBase.
389 *
390 * @note This function unbinds this RefBase object from the
391 * original RefCounter object, and then binds it to the
392 * newly constructed RefCounter object.
393 */
394 RefBase &operator=(const RefBase &);
395
396 /**
397 * @brief Move constructor of RefBase.
398 */
399 RefBase(RefBase &&other) noexcept;
400
401 /**
402 * @brief Move assignment operator of RefBase.
403 *
404 * @note This function binds this RefBase object with the RefCounter
405 * object of the argument `other`, which will unbind the
406 * RefCounter object. No counts operation will be processed.
407 */
408 RefBase &operator=(RefBase &&other) noexcept;
409
410 virtual ~RefBase();
411
412 /**
413 * @brief Callback function to deallocate this object.
414 *
415 * This function provides the default implementation to deallocate
416 * this RefBase object by simply calling `delete(this)`.
417 */
418 virtual void RefPtrCallback();
419
420 /**
421 * @brief Extends the life time of the RefBase object.
422 *
423 * @note The object whose life time has been extended will not be
424 * deallocated if the count of weak references, instead of strong
425 * references, reaches 0.
426 */
427 void ExtendObjectLifetime();
428
429 /**
430 * @brief Increments the count of strong references.
431 *
432 * `OnFirstStrongRef()`, which is an empty function by default,
433 * will be called when the first strong reference is established.
434 *
435 * @note This function automatically increments the count of weak
436 * references meanwhile.
437 */
438 void IncStrongRef(const void *objectId);
439
440 /**
441 * @brief Decrements the count of strong references.
442 *
443 * If the life time is not extended, this object will be deallocated
444 * when the count of strong references reaches 0.\n
445 * `OnLastStrongRef()`, which is an empty function by default,
446 * will be called when the last strong reference is deleted.
447 */
448 void DecStrongRef(const void *objectId);
449
450 /**
451 * @brief Gets the count of strong references.
452 *
453 * @return Count of strong references. The value is 0 if the
454 * corresponding RefCounter object does not exist.
455 * @note This function is valid only when corresponding RefCounter
456 * object exists.
457 */
458 int GetSptrRefCount();
459
460 /**
461 * @brief Creates a weak reference to this RefBase object.
462 *
463 * @param cookie Void pointer to this RefBase object.
464 * @return Pointer to the newly created WeakRefCounter object.
465 * @note Use this function with related functions of wptr.
466 * Do not use it independently.
467 */
468 WeakRefCounter *CreateWeakRef(void *cookie);
469
470 /**
471 * @brief Gets the pointer to corresponding counter object.
472 *
473 * @return Pointer to the counter object.
474 */
475 RefCounter *GetRefCounter() const;
476
477 /**
478 * @brief Increments the count of weak references.
479 *
480 * @note This function is valid only when corresponding RefCounter
481 * object exists.
482 */
483 void IncWeakRef(const void *objectId);
484
485 /**
486 * @brief Decrements the count of weak references.
487 *
488 * @note This function is valid only when corresponding RefCounter
489 * object exists.
490 */
491 void DecWeakRef(const void *objectId);
492
493 /**
494 * @brief Gets the count of weak references.
495 *
496 * @return Count of weak references. The value is 0 if the corresponding
497 * RefCounter object does not exist.
498 */
499 int GetWptrRefCount();
500
501 /**
502 * @brief Attempts to increment the count of strong references.
503 *
504 * `OnFirstStrongRef()`, which is an empty function by default, will be
505 * called when the first strong reference is established.
506 *
507 * @return `true` if the increment is successful; `false` otherwise.
508 * @note The count of attempts will increment by 1
509 * after a successful increment.
510 */
511 bool AttemptAcquire(const void *objectId);
512
513 /**
514 * @brief Check attempt acquire is setted,this interface is only for IPC use.
515 * This interface must come after the RefBase::AttemptIncStrong or RefBase::AttemptAcquire function,
516 * And ensuring thread safety in multi-threaded scenarios.
517 *
518 * @note This fuction is extracted from `IncStrongRef()`
519 * It is only for IPC use.
520 */
521 void CheckIsAttemptAcquireSet(const void *objectId);
522
523 /**
524 * @brief Attempts to increment the count of strong references.
525 *
526 * `OnFirstStrongRef()`, which is an empty function by default, will be
527 * called when the first strong reference is established.
528 * @return `true` if the increment is successful; `false` otherwise.
529 * @note Use this function in the copy constructor of sptr in scenario of
530 * interaction between sptr and wptr. Avoid using it independently.
531 */
532 bool AttemptIncStrongRef(const void *objectId);
533
534 // Only for IPC use.
535 /**
536 * @brief Attempts to increment the count of strong references.
537 *
538 * @return `true` if the increment is successful; `false` otherwise.
539 * @note If the operation is successful, the count of successful attempts
540 * will increment by 1.
541 * @note This function is a simplified version of `AttemptAcquire`.
542 * It is only for IPC use.
543 */
544 bool AttemptIncStrong(const void *objectId);
545
546 /**
547 * @brief Checks if the count of successful attempts is greater than 0.
548 *
549 * @return `true` if the count of successful attempts is greater than 0;
550 * `false` if the count of successful attempts is not greater than 0
551 * or the corresponding RefCounter object does not exist.
552 */
553 bool IsAttemptAcquireSet();
554
555 /**
556 * @brief Checks if the life time of this RefBase object has been extended.
557 *
558 * @return `true` if the life time of this RefBase object has been extended;
559 * `false` if the RefBase object has a normal life time or the corresponding
560 * RefCounter object does not exist.
561 */
562 bool IsExtendLifeTimeSet();
563
564 /**
565 * @brief Called when the first strong reference is established.
566 *
567 * @note It is an empty function by default.
568 */
569 virtual void OnFirstStrongRef(const void *);
570
571 /**
572 * @brief Called when the last strong reference is deleted.
573 *
574 * @note It is an empty function by default.
575 */
576 virtual void OnLastStrongRef(const void *);
577
578 /**
579 * @brief Called when the last weak reference is deleted.
580 *
581 * @note It is an empty function by default.
582 */
583 virtual void OnLastWeakRef(const void *);
584
585 /**
586 * @brief Called when `wptr::Promote()` is invoked.
587 *
588 * @return `true` if success; `false` otherwise.
589 */
590 virtual bool OnAttemptPromoted(const void *);
591
592 /**
593 * @brief Enables tracking of the RefBase object. This function will
594 * be implemented only if DEBUG_REFBASE, but not TRACK_ALL, is defined.
595 */
596 void EnableTracker();
597
598 #ifndef EMULATOR_PLATFORM
599 virtual bool CanPromote();
600 #endif
601
602 private:
603 RefCounter *refs_ = nullptr; // Pointer to the corresponding reference
604 // counter of this RefBase object
605 };
606
607 template <typename T>
608 class wptr;
609
610 /**
611 * @ingroup SmartPointer
612 * @brief Strong reference smart pointer to a RefBase object
613 * (or an object of its subclass).
614 *
615 * It directly reference the RefBase object.
616 *
617 * @tparam T Specific class type managed by sptr.
618 * This class must inherit from RefBase.
619 */
620 template <typename T>
621 class sptr {
622 friend class wptr<T>;
623
624 public:
625 sptr();
626
627 ~sptr();
628
629 /**
630 * @brief Create a new object with class type (T) and provide a new sptr to manage it.
631 *
632 * @note We strongly recommend using `sptr::MakeSptr` to create a object and manage it.
633 * This approach avoids object pointer leaks, which can avoid many potential memory problems.
634 *
635 * @return A sptr which manage a new object with class type (T).
636 * @param args Constructor parameters of the new object to be managed by sptr.
637 */
638 template <typename... Args>
639 static inline sptr<T> MakeSptr(Args&&... args);
640
641 /**
642 * @brief Constructor with the specified object to be managed.
643 * And We do not recommend using this interface to create an sptr object.
644 * Using the interface `sptr::MakeSptr` is better
645 *
646 * @note A null sptr will be created if `other` is `nullptr`.
647 * @param other Object to be managed by sptr.
648 */
649 sptr(T *other);
650
651 /**
652 * @brief Copy constructor for sptr with the managed class type (T).
653 *
654 * @param other Input sptr object.
655 */
656 sptr(const sptr<T> &other);
657
658 /**
659 * @brief Move constructor.
660 *
661 * @note `other` will be set to a null sptr.
662 * @param other Input sptr object.
663 */
664 sptr(sptr<T> &&other);
665
666 /**
667 * @brief Move assignment operator.
668 *
669 * @param other Input sptr object.
670 * @note The original strong reference in target sptr object will
671 * be removed.
672 */
673 sptr<T> &operator=(sptr<T> &&other);
674
675 /**
676 * @brief Copy Constructor for sptr with the managed class type (O).
677 *
678 * @tparam O Another specific class type managed by `other`.
679 * @param other Input sptr object.
680 */
681 template <typename O>
682 sptr(const sptr<O> &other);
683
684 /**
685 * @brief Constructor used to promote the process of wptr.
686 *
687 * @param p WeakRefCounter object which hold the reference to the
688 * managed object.
689 * @param force Used to distinguish from other constructors.
690 */
691 inline sptr(WeakRefCounter *p, bool force);
692
693 /**
694 * @brief Gets the pointer to the managed object.
695 *
696 * @return Pointer of the specific managed class type.
697 */
GetRefPtr()698 inline T *GetRefPtr() const
699 {
700 return refs_;
701 }
702
703 /**
704 * @brief Sets the pointer to the managed object.
705 *
706 * @param other Another pointer object to be managed by sptr.
707 * @note Avoid using this function independently. Otherwise,
708 * a mismatch of the reference count will arise, leading to memory problems.
709 */
710 inline void ForceSetRefPtr(T *other);
711
712 /**
713 * @brief Removes the reference to the managed object held by current sptr.
714 *
715 * @note This function will make this sptr a "null sptr".
716 */
717 void clear();
718
719 /**
720 * @brief Type conversion operator.
721 *
722 * @return Raw pointer to the managed object.
723 * @note The sptr object will not be converted. Only the member raw
724 * pointer will be returned.
725 */
726 inline operator T *() const
727 {
728 return refs_;
729 }
730
731 /**
732 * @brief Explicit boolean conversion operator.
733 *
734 * @return `true` if refbase object is not a "null ptr"; `false` otherwise.
735 */
736 inline explicit operator bool() const
737 {
738 return refs_ != nullptr;
739 }
740
741 /**
742 * @brief Dereference operator.
743 *
744 * This function will return the object managed by this sptr.
745 *
746 * @return Reference to the specific object managed by sptr.
747 */
748 inline T &operator*() const
749 {
750 return *refs_;
751 }
752
753 /**
754 * @brief Member selection operator.
755 *
756 * This function will return the specified member of the object
757 * managed by this sptr.
758 */
759 inline T *operator->() const
760 {
761 return refs_;
762 }
763
764 /**
765 * @brief Copy assignment operator with the specified object to be managed.
766 * And We do not recommend using this interface to create an sptr object.
767 * Using the interface `sptr::MakeSptr` is better.
768 *
769 * @note The original reference will be removed, and a new reference to the
770 * input object will be established.
771 * @param other Another object to be managed by this sptr.
772 */
773 sptr<T> &operator=(T *other);
774
775 /**
776 * @brief Copy assignment operator for sptr with
777 * the same managed class type (T).
778 *
779 * @note The original reference will be removed, and the same object
780 * with the input sptr object will be managed by this sptr.
781 * @param other Another sptr object with the same managed class type (T).
782 */
783 sptr<T> &operator=(const sptr<T> &other);
784
785 /**
786 * @brief Copy assignment operator for wptr with
787 * the same managed class type (T).
788 *
789 * @note The original reference will be removed, and the same object
790 * with the input wptr object will be managed by this sptr.
791 * @note If the operation fails, this sptr will turn to be a "null sptr".
792 * @param other Another wptr object with the same managed class type (T).
793 */
794 sptr<T> &operator=(const wptr<T> &other);
795
796 /**
797 * @brief Copy assignment operator for sptr with
798 * a different managed class type (O).
799 *
800 * @note The original reference will be removed, and the same object
801 * with the input sptr object will be managed by this sptr.
802 * @note This sptr will interpret the managed object as the type (T).
803 * @param other Another sptr object with a different managed class type (O).
804 */
805 template <typename O>
806 sptr<T> &operator=(const sptr<O> &other);
807
808 /**
809 * @brief Equal-to operator between the sptr and raw pointer.
810 *
811 * @param other Input raw pointer.
812 * @return `true` if the sptr points to the same object with input
813 * raw pointer; `false` otherwise.
814 */
815 bool operator==(const T *other) const;
816
817 /**
818 * @brief Not-equal-to operator between the sptr and raw pointer.
819 *
820 * @param other Input raw pointer.
821 * @return `true` if the sptr does not point to the same object
822 * with input raw pointer; `false` otherwise.
823 */
824 inline bool operator!=(const T *other) const
825 {
826 return !operator==(other);
827 }
828
829 /**
830 * @brief Equal-to operator between the sptr and wptr.
831 *
832 * @param other Input wptr.
833 * @return `true` if the same object is managed by the sptr and wptr;
834 * `false` otherwise.
835 */
836 bool operator==(const wptr<T> &other) const;
837
838 /**
839 * @brief Not-equal-to operator between the sptr and wptr.
840 *
841 * @param other Input wptr.
842 * @return `true` if different objects are managed by the sptr and wptr;
843 * `false` otherwise.
844 */
845 inline bool operator!=(const wptr<T> &other) const
846 {
847 return !operator==(other);
848 }
849
850 /**
851 * @brief Equal-to operator between two sptrs.
852 *
853 * @param other Input sptr.
854 * @return `true` if the same object is managed by two sptrs;
855 * `false` otherwise.
856 */
857 bool operator==(const sptr<T> &other) const;
858
859 /**
860 * @brief Not-equal-to operator between sptrs.
861 *
862 * @param other Input sptr.
863 * @return `true` if different objects are managed by two sptrs;
864 * `false` otherwise.
865 */
866 inline bool operator!=(const sptr<T> &other) const
867 {
868 return !operator==(other);
869 }
870
871 private:
872 T *refs_ = nullptr; // Raw pointer to the specific managed object
873 };
874
875 template <typename T>
876 template <typename... Args>
MakeSptr(Args &&...args)877 sptr<T> sptr<T>::MakeSptr(Args&&... args)
878 {
879 T *ptr = new T(std::forward<Args>(args)...);
880 sptr<T> res;
881 res.ForceSetRefPtr(ptr);
882 ptr->IncStrongRef(ptr);
883 return res;
884 }
885
886 template <typename T>
ForceSetRefPtr(T * other)887 inline void sptr<T>::ForceSetRefPtr(T *other)
888 {
889 refs_ = other;
890 }
891
892 template <typename T>
sptr()893 inline sptr<T>::sptr()
894 {
895 refs_ = nullptr;
896 }
897
898 template <typename T>
sptr(T * other)899 inline sptr<T>::sptr(T *other)
900 {
901 refs_ = other;
902 if (refs_ != nullptr) {
903 refs_->IncStrongRef(this);
904 }
905 }
906
907 template <typename T>
sptr(const sptr<T> & other)908 inline sptr<T>::sptr(const sptr<T> &other)
909 {
910 refs_ = other.GetRefPtr();
911 if (refs_ != nullptr) {
912 refs_->IncStrongRef(this);
913 }
914 }
915
916 template <typename T>
sptr(sptr<T> && other)917 sptr<T>::sptr(sptr<T> &&other)
918 {
919 refs_ = other.GetRefPtr();
920 other.ForceSetRefPtr(nullptr);
921 }
922
923 template <typename T>
924 sptr<T> &sptr<T>::operator=(sptr<T> &&other)
925 {
926 if (refs_ != nullptr) {
927 refs_->DecStrongRef(this);
928 }
929 refs_ = other.GetRefPtr();
930 other.ForceSetRefPtr(nullptr);
931 return *this;
932 }
933
934 template <typename T>
935 template <typename O>
sptr(const sptr<O> & other)936 sptr<T>::sptr(const sptr<O> &other) : refs_(other.GetRefPtr())
937 {
938 if (refs_ != nullptr) {
939 refs_->IncStrongRef(this);
940 }
941 }
942
943 template <typename T>
944 inline sptr<T> &sptr<T>::operator=(T *other)
945 {
946 if (other != nullptr) {
947 other->IncStrongRef(this);
948 }
949
950 if (refs_ != nullptr) {
951 refs_->DecStrongRef(this);
952 }
953
954 refs_ = other;
955 return *this;
956 }
957
958 template <typename T>
959 inline sptr<T> &sptr<T>::operator=(const sptr<T> &other)
960 {
961 T *otherRef(other.GetRefPtr());
962 if (otherRef != nullptr) {
963 otherRef->IncStrongRef(this);
964 }
965
966 if (refs_ != nullptr) {
967 refs_->DecStrongRef(this);
968 }
969
970 refs_ = otherRef;
971 return *this;
972 }
973
974 template <typename T>
975 inline sptr<T> &sptr<T>::operator=(const wptr<T> &other)
976 {
977 if (refs_ != nullptr) {
978 refs_->DecStrongRef(this);
979 }
980 if ((other != nullptr) && other.AttemptIncStrongRef(this)) {
981 refs_ = other.GetRefPtr();
982 } else {
983 refs_ = nullptr;
984 }
985
986 return *this;
987 }
988
989 template <typename T>
990 template <typename O>
991 sptr<T> &sptr<T>::operator=(const sptr<O> &other)
992 {
993 T *otherRef(other.GetRefPtr());
994 if (otherRef != nullptr) {
995 otherRef->IncStrongRef(this);
996 }
997
998 if (refs_ != nullptr) {
999 refs_->DecStrongRef(this);
1000 }
1001
1002 refs_ = otherRef;
1003 return *this;
1004 }
1005
1006 template <typename T>
1007 inline bool sptr<T>::operator==(const T *other) const
1008 {
1009 return other == refs_;
1010 }
1011
1012 template <typename T>
1013 inline bool sptr<T>::operator==(const wptr<T> &other) const
1014 {
1015 return refs_ == other.GetRefPtr();
1016 }
1017
1018 template <typename T>
1019 inline bool sptr<T>::operator==(const sptr<T> &other) const
1020 {
1021 return refs_ == other.GetRefPtr();
1022 }
1023
1024 template<typename T>
clear()1025 void sptr<T>::clear()
1026 {
1027 if (refs_) {
1028 refs_->DecStrongRef(this);
1029 refs_ = 0;
1030 }
1031 }
1032
1033 template <typename T>
~sptr()1034 inline sptr<T>::~sptr()
1035 {
1036 if (refs_ != nullptr) {
1037 refs_->DecStrongRef(this);
1038 }
1039 }
1040
1041 template <typename T>
sptr(WeakRefCounter * p,bool)1042 inline sptr<T>::sptr(WeakRefCounter *p, bool /* force */)
1043 {
1044 if ((p != nullptr) && p->AttemptIncStrongRef(this)) {
1045 refs_ = reinterpret_cast<T *>(p->GetRefPtr());
1046 } else {
1047 refs_ = nullptr;
1048 }
1049 }
1050
1051 /**
1052 * @ingroup SmartPointer
1053 * @brief Weak reference smart pointer to a RefBase object
1054 * (or an object of its subclass).
1055 *
1056 * A weak reference indirectly references the RefBase object
1057 * and directly references the WeakRefCounter object.
1058 *
1059 * @tparam T Specific class type managed by wptr.
1060 * This class must inherit from RefBase.
1061 */
1062 template <typename T>
1063 class wptr {
1064 template <typename O>
1065 friend class wptr;
1066
1067 public:
1068 wptr();
1069
1070 /**
1071 * @brief Constructor with the specified object to be managed.
1072 *
1073 * This function will create WeakRefCounter object for `other`
1074 * and set the count of weak references to 1.
1075 *
1076 * @note A WeakRefCounter object will not be created if `other`
1077 * is a `nullptr`.
1078 *
1079 * @param other Object to be managed by wptr.
1080 */
1081 wptr(T *other);
1082
1083 /**
1084 * @brief Copy constructor for wptr with the same managed class type (T).
1085 *
1086 * This function will share the WeakRefCounter object of `other` with this
1087 * wptr and set the count of weak references properly.
1088 *
1089 * @param other Another wptr with the same managed class type (T).
1090 */
1091 wptr(const wptr<T> &other);
1092
1093 /**
1094 * @brief Copy constructor for sptr with the same managed class type (T).
1095 *
1096 * This function will create a WeakRefCounter object for the managed
1097 * object of `other`, and set the count of weak references properly.
1098 *
1099 * @param other Another sptr with the same managed class type (T).
1100 * @tparam T Specific class type managed by `other`.
1101 */
1102 wptr(const sptr<T> &other);
1103
1104 /**
1105 * @brief Copy constructor for wptr with a different managed class type (O).
1106 *
1107 * This function is the same as wptr<T>::wptr(const wptr<T> &other).
1108 *
1109 * @tparam O Class type managed by `other`.
1110 * @param other Another wptr with a different managed class type (O).
1111 * @tparam T Specific class type managed by `other`.
1112 */
1113 template <typename O>
1114 wptr(const wptr<O> &other);
1115
1116 /**
1117 * @brief Copy constructor for sptr with a different managed class type (O).
1118 *
1119 * This function is the same as wptr<T>::wptr(const sptr<T> &other).
1120 *
1121 * @param other Another sptr with the same managed class type (O).
1122 * @tparam T Specific class type managed by `other`.
1123 */
1124 template <typename O>
1125 wptr(const sptr<O> &other);
1126
1127 /**
1128 * @brief Copy assignment operator with the specified object to be managed.
1129 *
1130 * @note The current wptr will unbind the original WeakRefCounter object,
1131 * create a new WeakRefCounter object, and then set the count of weak
1132 * references properly.
1133 * @param other Another object to be managed by this wptr.
1134 */
1135 wptr<T> &operator=(T *other);
1136
1137 /**
1138 * @brief Copy assignment operator with the specified object to be managed.
1139 *
1140 * @note Same with wptr<T> &operator=(T *other), but a pointer type casting
1141 * which will not affect the type of `*other` is processed.
1142 * @tparam O Specific class type managed by `other`.
1143 * @param other Another object to be managed by this wptr.
1144 *
1145 */
1146 template <typename O>
1147 wptr<T> &operator=(O *other);
1148
1149 /**
1150 * @brief Copy assignment operator for wptr with the same managed class
1151 * type (T).
1152 *
1153 * @note The current wptr will unbind the original WeakRefCounter object,
1154 * share the WeakRefCounter object with `other`, and then set the count of
1155 * weak references properly.
1156 * @param other Another wptr object. Objects managed by it will also be
1157 * managed by this wptr.
1158 */
1159 wptr<T> &operator=(const wptr<T> &other);
1160
1161 /**
1162 * @brief Copy assignment operator for sptr with the same managed class
1163 * type (T).
1164 *
1165 * @note The current wptr will unbind the original WeakRefCounter object,
1166 * create a new WeakRefCounter object, and then set the count of weak
1167 * references properly.
1168 * @param other A sptr object. Objects managed by it will also be
1169 * managed by this wptr.
1170 */
1171 wptr<T> &operator=(const sptr<T> &other);
1172
1173 /**
1174 * @brief Copy assignment operator for wptr with a different managed class
1175 * type (O).
1176 *
1177 * @note This function is the same as wptr<T> &operator=(const wptr<T> &).
1178 * Note that no cast here is processed.
1179 * @param other An wptr object. Objects managed by it will also be
1180 * managed by this wptr.
1181 * @tparam O Specific class type managed by `other`.
1182 */
1183 template <typename O>
1184 wptr<T> &operator=(const wptr<O> &other);
1185
1186 /**
1187 * @brief Copy assignment operator for sptr with a different managed class
1188 * type (O).
1189 *
1190 * @note This function is the same as
1191 * wptr<T> &wptr<T>::operator=(const sptr<T> &).
1192 * Note that no cast here is processed.
1193 * @param other An sptr object. Objects managed by it will also be
1194 * managed by this wptr.
1195 * @tparam O Specific class type managed by `other`.
1196 */
1197 template <typename O>
1198 wptr<T> &operator=(const sptr<O> &other);
1199
1200 /**
1201 * @brief Dereference operator.
1202 *
1203 * This function will return the object managed by this wptr.
1204 *
1205 * @return Specific object managed by wptr.
1206 */
1207 inline T &operator*() const
1208 {
1209 return *GetRefPtr();
1210 }
1211
1212 /**
1213 * @brief Member selection operator.
1214 *
1215 * This function will return the specified object member managed
1216 * by this wptr.
1217 */
1218 inline T *operator->() const
1219 {
1220 return reinterpret_cast<T *>(refs_->GetRefPtr());
1221 }
1222
1223 /**
1224 * @brief Equal-to operator between the wptr and raw pointer.
1225 *
1226 * @param other Input raw pointer.
1227 * @return `true` if two pointers have the same value; `false` otherwise.
1228 */
1229 bool operator==(const T *other) const;
1230
1231 /**
1232 * @brief Not-equal-to operator between the wptr and raw pointer.
1233 *
1234 * @param other Input raw pointer.
1235 * @return `true` if two pointers have different values; `false` otherwise.
1236 */
1237 inline bool operator!=(const T *other) const
1238 {
1239 return !operator==(other);
1240 };
1241
1242 /**
1243 * @brief Equal-to operator between two wptrs.
1244 *
1245 * @param other Input reference to a wptr object.
1246 * @return `true` if two pointers have the same value; `false` otherwise.
1247 */
1248 bool operator==(const wptr<T> &other) const;
1249
1250 /**
1251 * @brief Not-equal-to operator between two wptrs.
1252 *
1253 * @param other Input reference to a wptr object.
1254 * @return `true` if two pointers have different values; `false` otherwise.
1255 */
1256 inline bool operator!=(const wptr<T> &other) const
1257 {
1258 return !operator==(other);
1259 }
1260
1261 /**
1262 * @brief Equal-to operator between the wptr and input sptr object.
1263 *
1264 * @param other Input reference to an sptr object.
1265 * @return true` if two pointers have the same value; `false` otherwise.
1266 */
1267 bool operator==(const sptr<T> &other) const;
1268
1269 /**
1270 * @brief Not-equal-to operator between the wptr and input sptr object.
1271 *
1272 * @param other Input reference to an sptr object.
1273 * @return `true` if two pointers have different values; `false` otherwise.
1274 */
1275 inline bool operator!=(const sptr<T> &other) const
1276 {
1277 return !operator==(other);
1278 }
1279
1280 /**
1281 * @brief Gets the pointer to the RefBase object.
1282 *
1283 * @return Raw pointer to the RefBase object.
1284 * @note `nullptr` will be returned if the managed object has been
1285 * deallocated.
1286 */
1287 T *GetRefPtr() const;
1288
1289 /**
1290 * @brief Gets the count of weak references in a WeakRefCounter object.
1291 *
1292 * The value indicates how many wptrs share the same WeakRefCounter object.
1293 *
1294 * @return Count of weak references.
1295 * @note Only for test.
1296 */
GetWeakRefCount()1297 inline int GetWeakRefCount() const
1298 {
1299 return refs_->GetWeakRefCount();
1300 }
1301
1302 /**
1303 * @brief Attempts to increment the count of strong references in
1304 * the managed object.
1305 *
1306 * @return `true` if the increment is successful; `false` otherwise.
1307 * @note Avoid using this function independently. Use `promote()` instead.
1308 */
AttemptIncStrongRef(const void * objectId)1309 inline bool AttemptIncStrongRef(const void *objectId) const
1310 {
1311 return refs_->AttemptIncStrongRef(objectId);
1312 }
1313
1314 /**
1315 * @brief Promotes a wptr to an sptr.
1316 *
1317 * This function will create an sptr object based on the object
1318 * managed by this wptr.
1319 *
1320 * @note The original weak reference will be retained.
1321 * If the promotion fails, a "null sptr" will be returned.
1322 */
1323 const sptr<T> promote() const;
1324
1325 ~wptr();
1326
1327 private:
1328 WeakRefCounter *refs_ = nullptr; // Pointer to the corresponding WeakRefCounter object
1329 };
1330
1331 template <typename T>
GetRefPtr()1332 inline T *wptr<T>::GetRefPtr() const
1333 {
1334 return (refs_ != nullptr) ? reinterpret_cast<T *>(refs_->GetRefPtr()) : nullptr;
1335 }
1336
1337 template <typename T>
wptr()1338 wptr<T>::wptr()
1339 {
1340 refs_ = nullptr;
1341 }
1342
1343 template <typename T>
wptr(T * other)1344 wptr<T>::wptr(T *other)
1345 {
1346 if (other != nullptr) {
1347 refs_ = other->CreateWeakRef(other);
1348 if (refs_ != nullptr) {
1349 refs_->IncWeakRefCount(this);
1350 }
1351 } else {
1352 refs_ = nullptr;
1353 }
1354 }
1355
1356 template <typename T>
wptr(const wptr<T> & other)1357 wptr<T>::wptr(const wptr<T> &other)
1358 {
1359 refs_ = other.refs_;
1360 if (refs_ != nullptr) {
1361 refs_->IncWeakRefCount(this);
1362 }
1363 }
1364
1365 template <typename T>
wptr(const sptr<T> & other)1366 wptr<T>::wptr(const sptr<T> &other)
1367 {
1368 if (other.GetRefPtr() != nullptr) {
1369 refs_ = other->CreateWeakRef(other.GetRefPtr());
1370 if (refs_ != nullptr) {
1371 refs_->IncWeakRefCount(this);
1372 }
1373 }
1374 }
1375
1376 template <typename T>
1377 template <typename O>
wptr(const wptr<O> & other)1378 wptr<T>::wptr(const wptr<O> &other)
1379 {
1380 refs_ = other.refs_;
1381 if (refs_ != nullptr) {
1382 refs_->IncWeakRefCount(this);
1383 }
1384 }
1385
1386 template <typename T>
1387 template <typename O>
wptr(const sptr<O> & other)1388 wptr<T>::wptr(const sptr<O> &other)
1389 {
1390 if (other.GetRefPtr() != nullptr) {
1391 refs_ = other->CreateWeakRef(other.GetRefPtr());
1392 if (refs_ != nullptr) {
1393 refs_->IncWeakRefCount(this);
1394 }
1395 }
1396 }
1397
1398 template <typename T>
1399 wptr<T> &wptr<T>::operator=(T *other)
1400 {
1401 WeakRefCounter *newWeakRef = nullptr;
1402 if (other != nullptr) {
1403 newWeakRef = other->CreateWeakRef(other);
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=(O *other)
1420 {
1421 T *object = reinterpret_cast<T *>(other);
1422 WeakRefCounter *newWeakRef = nullptr;
1423 if (object != nullptr) {
1424 newWeakRef = object->CreateWeakRef(object);
1425 if (newWeakRef != nullptr) {
1426 newWeakRef->IncWeakRefCount(this);
1427 }
1428 }
1429
1430 if (refs_ != nullptr) {
1431 refs_->DecWeakRefCount(this);
1432 }
1433
1434 refs_ = newWeakRef;
1435 return *this;
1436 }
1437
1438 template <typename T>
1439 inline wptr<T> &wptr<T>::operator=(const wptr<T> &other)
1440 {
1441 if (other.refs_ != nullptr) {
1442 other.refs_->IncWeakRefCount(this);
1443 }
1444
1445 if (refs_ != nullptr) {
1446 refs_->DecWeakRefCount(this);
1447 }
1448
1449 refs_ = other.refs_;
1450 return *this;
1451 }
1452
1453 template <typename T>
1454 inline wptr<T> &wptr<T>::operator=(const sptr<T> &other)
1455 {
1456 WeakRefCounter *newWeakRef = nullptr;
1457 if (other.GetRefPtr() != nullptr) {
1458 newWeakRef = other->CreateWeakRef(other.GetRefPtr());
1459 if (newWeakRef != nullptr) {
1460 newWeakRef->IncWeakRefCount(this);
1461 }
1462 }
1463
1464 if (refs_ != nullptr) {
1465 refs_->DecWeakRefCount(this);
1466 }
1467
1468 refs_ = newWeakRef;
1469 return *this;
1470 }
1471
1472 template <typename T>
1473 template <typename O>
1474 wptr<T> &wptr<T>::operator=(const wptr<O> &other)
1475 {
1476 if (other.refs_ != nullptr) {
1477 other.refs_->IncWeakRefCount(this);
1478 }
1479
1480 if (refs_ != nullptr) {
1481 refs_->DecWeakRefCount(this);
1482 }
1483
1484 refs_ = other.refs_;
1485 return *this;
1486 }
1487
1488 template <typename T>
1489 template <typename O>
1490 wptr<T> &wptr<T>::operator=(const sptr<O> &other)
1491 {
1492 WeakRefCounter *newWeakRef = nullptr;
1493 if (other.GetRefPtr() != nullptr) {
1494 newWeakRef = other->CreateWeakRef(other.GetRefPtr());
1495 if (newWeakRef != nullptr) {
1496 newWeakRef->IncWeakRefCount(this);
1497 }
1498 }
1499
1500 if (refs_ != nullptr) {
1501 refs_->DecWeakRefCount(this);
1502 }
1503
1504 refs_ = newWeakRef;
1505 return *this;
1506 }
1507
1508 template <typename T>
1509 inline bool wptr<T>::operator==(const T *other) const
1510 {
1511 return GetRefPtr() == other;
1512 }
1513
1514 template <typename T>
1515 inline bool wptr<T>::operator==(const wptr<T> &other) const
1516 {
1517 return GetRefPtr() == other.GetRefPtr();
1518 }
1519
1520 template <typename T>
1521 inline bool wptr<T>::operator==(const sptr<T> &other) const
1522 {
1523 return GetRefPtr() == other.GetRefPtr();
1524 }
1525
1526 template <typename T>
promote()1527 inline const sptr<T> wptr<T>::promote() const
1528 {
1529 return sptr<T>(refs_, true);
1530 }
1531
1532 template <typename T>
~wptr()1533 inline wptr<T>::~wptr()
1534 {
1535 if (refs_ != nullptr) {
1536 refs_->DecWeakRefCount(this);
1537 }
1538 }
1539
1540 } // namespace OHOS
1541
1542 #endif
1543
1544 /**@}*/
1545