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 Create a new object with class type (T) and provide a new sptr to manage it.
597 *
598 * @note We strongly recommend using `sptr::MakeSptr` to create a object and manage it.
599 * This approach avoids object pointer leaks, which can avoid many potential memory problems.
600 *
601 * @return A sptr which manage a new object with class type (T).
602 * @param args Constructor parameters of the new object to be managed by sptr.
603 */
604 template <typename... Args>
605 static inline sptr<T> MakeSptr(Args&&... args);
606
607 /**
608 * @brief Constructor with the specified object to be managed.
609 * And We do not recommend using this interface to create an sptr object.
610 * Using the interface `sptr::MakeSptr` is better
611 *
612 * @note A null sptr will be created if `other` is `nullptr`.
613 * @param other Object to be managed by sptr.
614 */
615 sptr(T *other);
616
617 /**
618 * @brief Copy constructor for sptr with the managed class type (T).
619 *
620 * @param other Input sptr object.
621 */
622 sptr(const sptr<T> &other);
623
624 /**
625 * @brief Move constructor.
626 *
627 * @note `other` will be set to a null sptr.
628 * @param other Input sptr object.
629 */
630 sptr(sptr<T> &&other);
631
632 /**
633 * @brief Move assignment operator.
634 *
635 * @param other Input sptr object.
636 * @note The original strong reference in target sptr object will
637 * be removed.
638 */
639 sptr<T> &operator=(sptr<T> &&other);
640
641 /**
642 * @brief Copy Constructor for sptr with the managed class type (O).
643 *
644 * @tparam O Another specific class type managed by `other`.
645 * @param other Input sptr object.
646 */
647 template <typename O>
648 sptr(const sptr<O> &other);
649
650 /**
651 * @brief Constructor used to promote the process of wptr.
652 *
653 * @param p WeakRefCounter object which hold the reference to the
654 * managed object.
655 * @param force Used to distinguish from other constructors.
656 */
657 inline sptr(WeakRefCounter *p, bool force);
658
659 /**
660 * @brief Gets the pointer to the managed object.
661 *
662 * @return Pointer of the specific managed class type.
663 */
GetRefPtr()664 inline T *GetRefPtr() const
665 {
666 return refs_;
667 }
668
669 /**
670 * @brief Sets the pointer to the managed object.
671 *
672 * @param other Another pointer object to be managed by sptr.
673 * @note Avoid using this function independently. Otherwise,
674 * a mismatch of the reference count will arise, leading to memory problems.
675 */
676 inline void ForceSetRefPtr(T *other);
677
678 /**
679 * @brief Removes the reference to the managed object held by current sptr.
680 *
681 * @note This function will make this sptr a "null sptr".
682 */
683 void clear();
684
685 /**
686 * @brief Type conversion operator.
687 *
688 * @return Raw pointer to the managed object.
689 * @note The sptr object will not be converted. Only the member raw
690 * pointer will be returned.
691 */
692 inline operator T *() const
693 {
694 return refs_;
695 }
696
697 /**
698 * @brief Explicit boolean conversion operator.
699 *
700 * @return `true` if refbase object is not a "null ptr"; `false` otherwise.
701 */
702 inline explicit operator bool() const
703 {
704 return refs_ != nullptr;
705 }
706
707 /**
708 * @brief Dereference operator.
709 *
710 * This function will return the object managed by this sptr.
711 *
712 * @return Reference to the specific object managed by sptr.
713 */
714 inline T &operator*() const
715 {
716 return *refs_;
717 }
718
719 /**
720 * @brief Member selection operator.
721 *
722 * This function will return the specified member of the object
723 * managed by this sptr.
724 */
725 inline T *operator->() const
726 {
727 return refs_;
728 }
729
730 /**
731 * @brief Copy assignment operator with the specified object to be managed.
732 * And We do not recommend using this interface to create an sptr object.
733 * Using the interface `sptr::MakeSptr` is better.
734 *
735 * @note The original reference will be removed, and a new reference to the
736 * input object will be established.
737 * @param other Another object to be managed by this sptr.
738 */
739 sptr<T> &operator=(T *other);
740
741 /**
742 * @brief Copy assignment operator for sptr with
743 * the same managed class type (T).
744 *
745 * @note The original reference will be removed, and the same object
746 * with the input sptr object will be managed by this sptr.
747 * @param other Another sptr object with the same managed class type (T).
748 */
749 sptr<T> &operator=(const sptr<T> &other);
750
751 /**
752 * @brief Copy assignment operator for wptr with
753 * the same managed class type (T).
754 *
755 * @note The original reference will be removed, and the same object
756 * with the input wptr object will be managed by this sptr.
757 * @note If the operation fails, this sptr will turn to be a "null sptr".
758 * @param other Another wptr object with the same managed class type (T).
759 */
760 sptr<T> &operator=(const wptr<T> &other);
761
762 /**
763 * @brief Copy assignment operator for sptr with
764 * a different managed class type (O).
765 *
766 * @note The original reference will be removed, and the same object
767 * with the input sptr object will be managed by this sptr.
768 * @note This sptr will interpret the managed object as the type (T).
769 * @param other Another sptr object with a different managed class type (O).
770 */
771 template <typename O>
772 sptr<T> &operator=(const sptr<O> &other);
773
774 /**
775 * @brief Equal-to operator between the sptr and raw pointer.
776 *
777 * @param other Input raw pointer.
778 * @return `true` if the sptr points to the same object with input
779 * raw pointer; `false` otherwise.
780 */
781 bool operator==(const T *other) const;
782
783 /**
784 * @brief Not-equal-to operator between the sptr and raw pointer.
785 *
786 * @param other Input raw pointer.
787 * @return `true` if the sptr does not point to the same object
788 * with input raw pointer; `false` otherwise.
789 */
790 inline bool operator!=(const T *other) const
791 {
792 return !operator==(other);
793 }
794
795 /**
796 * @brief Equal-to operator between the sptr and wptr.
797 *
798 * @param other Input wptr.
799 * @return `true` if the same object is managed by the sptr and wptr;
800 * `false` otherwise.
801 */
802 bool operator==(const wptr<T> &other) const;
803
804 /**
805 * @brief Not-equal-to operator between the sptr and wptr.
806 *
807 * @param other Input wptr.
808 * @return `true` if different objects are managed by the sptr and wptr;
809 * `false` otherwise.
810 */
811 inline bool operator!=(const wptr<T> &other) const
812 {
813 return !operator==(other);
814 }
815
816 /**
817 * @brief Equal-to operator between two sptrs.
818 *
819 * @param other Input sptr.
820 * @return `true` if the same object is managed by two sptrs;
821 * `false` otherwise.
822 */
823 bool operator==(const sptr<T> &other) const;
824
825 /**
826 * @brief Not-equal-to operator between sptrs.
827 *
828 * @param other Input sptr.
829 * @return `true` if different objects are managed by two sptrs;
830 * `false` otherwise.
831 */
832 inline bool operator!=(const sptr<T> &other) const
833 {
834 return !operator==(other);
835 }
836
837 private:
838 T *refs_ = nullptr; // Raw pointer to the specific managed object
839 };
840
841 template <typename T>
842 template <typename... Args>
MakeSptr(Args &&...args)843 sptr<T> sptr<T>::MakeSptr(Args&&... args)
844 {
845 T *ptr = new T(std::forward<Args>(args)...);
846 sptr<T> res;
847 res.ForceSetRefPtr(ptr);
848 ptr->IncStrongRef(ptr);
849 return res;
850 }
851
852 template <typename T>
ForceSetRefPtr(T * other)853 inline void sptr<T>::ForceSetRefPtr(T *other)
854 {
855 refs_ = other;
856 }
857
858 template <typename T>
sptr()859 inline sptr<T>::sptr()
860 {
861 refs_ = nullptr;
862 }
863
864 template <typename T>
sptr(T * other)865 inline sptr<T>::sptr(T *other)
866 {
867 refs_ = other;
868 if (refs_ != nullptr) {
869 refs_->IncStrongRef(this);
870 }
871 }
872
873 template <typename T>
sptr(const sptr<T> & other)874 inline sptr<T>::sptr(const sptr<T> &other)
875 {
876 refs_ = other.GetRefPtr();
877 if (refs_ != nullptr) {
878 refs_->IncStrongRef(this);
879 }
880 }
881
882 template <typename T>
sptr(sptr<T> && other)883 sptr<T>::sptr(sptr<T> &&other)
884 {
885 refs_ = other.GetRefPtr();
886 other.ForceSetRefPtr(nullptr);
887 }
888
889 template <typename T>
890 sptr<T> &sptr<T>::operator=(sptr<T> &&other)
891 {
892 if (refs_ != nullptr) {
893 refs_->DecStrongRef(this);
894 }
895 refs_ = other.GetRefPtr();
896 other.ForceSetRefPtr(nullptr);
897 return *this;
898 }
899
900 template <typename T>
901 template <typename O>
sptr(const sptr<O> & other)902 sptr<T>::sptr(const sptr<O> &other) : refs_(other.GetRefPtr())
903 {
904 if (refs_ != nullptr) {
905 refs_->IncStrongRef(this);
906 }
907 }
908
909 template <typename T>
910 inline sptr<T> &sptr<T>::operator=(T *other)
911 {
912 if (other != nullptr) {
913 other->IncStrongRef(this);
914 }
915
916 if (refs_ != nullptr) {
917 refs_->DecStrongRef(this);
918 }
919
920 refs_ = other;
921 return *this;
922 }
923
924 template <typename T>
925 inline sptr<T> &sptr<T>::operator=(const sptr<T> &other)
926 {
927 T *otherRef(other.GetRefPtr());
928 if (otherRef != nullptr) {
929 otherRef->IncStrongRef(this);
930 }
931
932 if (refs_ != nullptr) {
933 refs_->DecStrongRef(this);
934 }
935
936 refs_ = otherRef;
937 return *this;
938 }
939
940 template <typename T>
941 inline sptr<T> &sptr<T>::operator=(const wptr<T> &other)
942 {
943 if (refs_ != nullptr) {
944 refs_->DecStrongRef(this);
945 }
946 if ((other != nullptr) && other.AttemptIncStrongRef(this)) {
947 refs_ = other.GetRefPtr();
948 } else {
949 refs_ = nullptr;
950 }
951
952 return *this;
953 }
954
955 template <typename T>
956 template <typename O>
957 sptr<T> &sptr<T>::operator=(const sptr<O> &other)
958 {
959 T *otherRef(other.GetRefPtr());
960 if (otherRef != nullptr) {
961 otherRef->IncStrongRef(this);
962 }
963
964 if (refs_ != nullptr) {
965 refs_->DecStrongRef(this);
966 }
967
968 refs_ = otherRef;
969 return *this;
970 }
971
972 template <typename T>
973 inline bool sptr<T>::operator==(const T *other) const
974 {
975 return other == refs_;
976 }
977
978 template <typename T>
979 inline bool sptr<T>::operator==(const wptr<T> &other) const
980 {
981 return refs_ == other.GetRefPtr();
982 }
983
984 template <typename T>
985 inline bool sptr<T>::operator==(const sptr<T> &other) const
986 {
987 return refs_ == other.GetRefPtr();
988 }
989
990 template<typename T>
clear()991 void sptr<T>::clear()
992 {
993 if (refs_) {
994 refs_->DecStrongRef(this);
995 refs_ = 0;
996 }
997 }
998
999 template <typename T>
~sptr()1000 inline sptr<T>::~sptr()
1001 {
1002 if (refs_ != nullptr) {
1003 refs_->DecStrongRef(this);
1004 }
1005 }
1006
1007 template <typename T>
sptr(WeakRefCounter * p,bool)1008 inline sptr<T>::sptr(WeakRefCounter *p, bool /* force */)
1009 {
1010 if ((p != nullptr) && p->AttemptIncStrongRef(this)) {
1011 refs_ = reinterpret_cast<T *>(p->GetRefPtr());
1012 } else {
1013 refs_ = nullptr;
1014 }
1015 }
1016
1017 /**
1018 * @ingroup SmartPointer
1019 * @brief Weak reference smart pointer to a RefBase object
1020 * (or an object of its subclass).
1021 *
1022 * A weak reference indirectly references the RefBase object
1023 * and directly references the WeakRefCounter object.
1024 *
1025 * @tparam T Specific class type managed by wptr.
1026 * This class must inherit from RefBase.
1027 */
1028 template <typename T>
1029 class wptr {
1030 template <typename O>
1031 friend class wptr;
1032
1033 public:
1034 wptr();
1035
1036 /**
1037 * @brief Constructor with the specified object to be managed.
1038 *
1039 * This function will create WeakRefCounter object for `other`
1040 * and set the count of weak references to 1.
1041 *
1042 * @note A WeakRefCounter object will not be created if `other`
1043 * is a `nullptr`.
1044 *
1045 * @param other Object to be managed by wptr.
1046 */
1047 wptr(T *other);
1048
1049 /**
1050 * @brief Copy constructor for wptr with the same managed class type (T).
1051 *
1052 * This function will share the WeakRefCounter object of `other` with this
1053 * wptr and set the count of weak references properly.
1054 *
1055 * @param other Another wptr with the same managed class type (T).
1056 */
1057 wptr(const wptr<T> &other);
1058
1059 /**
1060 * @brief Copy constructor for sptr with the same managed class type (T).
1061 *
1062 * This function will create a WeakRefCounter object for the managed
1063 * object of `other`, and set the count of weak references properly.
1064 *
1065 * @param other Another sptr with the same managed class type (T).
1066 * @tparam T Specific class type managed by `other`.
1067 */
1068 wptr(const sptr<T> &other);
1069
1070 /**
1071 * @brief Copy constructor for wptr with a different managed class type (O).
1072 *
1073 * This function is the same as wptr<T>::wptr(const wptr<T> &other).
1074 *
1075 * @tparam O Class type managed by `other`.
1076 * @param other Another wptr with a different managed class type (O).
1077 * @tparam T Specific class type managed by `other`.
1078 */
1079 template <typename O>
1080 wptr(const wptr<O> &other);
1081
1082 /**
1083 * @brief Copy constructor for sptr with a different managed class type (O).
1084 *
1085 * This function is the same as wptr<T>::wptr(const sptr<T> &other).
1086 *
1087 * @param other Another sptr with the same managed class type (O).
1088 * @tparam T Specific class type managed by `other`.
1089 */
1090 template <typename O>
1091 wptr(const sptr<O> &other);
1092
1093 /**
1094 * @brief Copy assignment operator with the specified object to be managed.
1095 *
1096 * @note The current wptr will unbind the original WeakRefCounter object,
1097 * create a new WeakRefCounter object, and then set the count of weak
1098 * references properly.
1099 * @param other Another object to be managed by this wptr.
1100 */
1101 wptr<T> &operator=(T *other);
1102
1103 /**
1104 * @brief Copy assignment operator with the specified object to be managed.
1105 *
1106 * @note Same with wptr<T> &operator=(T *other), but a pointer type casting
1107 * which will not affect the type of `*other` is processed.
1108 * @tparam O Specific class type managed by `other`.
1109 * @param other Another object to be managed by this wptr.
1110 *
1111 */
1112 template <typename O>
1113 wptr<T> &operator=(O *other);
1114
1115 /**
1116 * @brief Copy assignment operator for wptr with the same managed class
1117 * type (T).
1118 *
1119 * @note The current wptr will unbind the original WeakRefCounter object,
1120 * share the WeakRefCounter object with `other`, and then set the count of
1121 * weak references properly.
1122 * @param other Another wptr object. Objects managed by it will also be
1123 * managed by this wptr.
1124 */
1125 wptr<T> &operator=(const wptr<T> &other);
1126
1127 /**
1128 * @brief Copy assignment operator for sptr with the same managed class
1129 * type (T).
1130 *
1131 * @note The current wptr will unbind the original WeakRefCounter object,
1132 * create a new WeakRefCounter object, and then set the count of weak
1133 * references properly.
1134 * @param other A sptr object. Objects managed by it will also be
1135 * managed by this wptr.
1136 */
1137 wptr<T> &operator=(const sptr<T> &other);
1138
1139 /**
1140 * @brief Copy assignment operator for wptr with a different managed class
1141 * type (O).
1142 *
1143 * @note This function is the same as wptr<T> &operator=(const wptr<T> &).
1144 * Note that no cast here is processed.
1145 * @param other An wptr object. Objects managed by it will also be
1146 * managed by this wptr.
1147 * @tparam O Specific class type managed by `other`.
1148 */
1149 template <typename O>
1150 wptr<T> &operator=(const wptr<O> &other);
1151
1152 /**
1153 * @brief Copy assignment operator for sptr with a different managed class
1154 * type (O).
1155 *
1156 * @note This function is the same as
1157 * wptr<T> &wptr<T>::operator=(const sptr<T> &).
1158 * Note that no cast here is processed.
1159 * @param other An sptr object. Objects managed by it will also be
1160 * managed by this wptr.
1161 * @tparam O Specific class type managed by `other`.
1162 */
1163 template <typename O>
1164 wptr<T> &operator=(const sptr<O> &other);
1165
1166 /**
1167 * @brief Dereference operator.
1168 *
1169 * This function will return the object managed by this wptr.
1170 *
1171 * @return Specific object managed by wptr.
1172 */
1173 inline T &operator*() const
1174 {
1175 return *GetRefPtr();
1176 }
1177
1178 /**
1179 * @brief Member selection operator.
1180 *
1181 * This function will return the specified object member managed
1182 * by this wptr.
1183 */
1184 inline T *operator->() const
1185 {
1186 return reinterpret_cast<T *>(refs_->GetRefPtr());
1187 }
1188
1189 /**
1190 * @brief Equal-to operator between the wptr and raw pointer.
1191 *
1192 * @param other Input raw pointer.
1193 * @return `true` if two pointers have the same value; `false` otherwise.
1194 */
1195 bool operator==(const T *other) const;
1196
1197 /**
1198 * @brief Not-equal-to operator between the wptr and raw pointer.
1199 *
1200 * @param other Input raw pointer.
1201 * @return `true` if two pointers have different values; `false` otherwise.
1202 */
1203 inline bool operator!=(const T *other) const
1204 {
1205 return !operator==(other);
1206 };
1207
1208 /**
1209 * @brief Equal-to operator between two wptrs.
1210 *
1211 * @param other Input reference to a wptr object.
1212 * @return `true` if two pointers have the same value; `false` otherwise.
1213 */
1214 bool operator==(const wptr<T> &other) const;
1215
1216 /**
1217 * @brief Not-equal-to operator between two wptrs.
1218 *
1219 * @param other Input reference to a wptr object.
1220 * @return `true` if two pointers have different values; `false` otherwise.
1221 */
1222 inline bool operator!=(const wptr<T> &other) const
1223 {
1224 return !operator==(other);
1225 }
1226
1227 /**
1228 * @brief Equal-to operator between the wptr and input sptr object.
1229 *
1230 * @param other Input reference to an sptr object.
1231 * @return true` if two pointers have the same value; `false` otherwise.
1232 */
1233 bool operator==(const sptr<T> &other) const;
1234
1235 /**
1236 * @brief Not-equal-to operator between the wptr and input sptr object.
1237 *
1238 * @param other Input reference to an sptr object.
1239 * @return `true` if two pointers have different values; `false` otherwise.
1240 */
1241 inline bool operator!=(const sptr<T> &other) const
1242 {
1243 return !operator==(other);
1244 }
1245
1246 /**
1247 * @brief Gets the pointer to the RefBase object.
1248 *
1249 * @return Raw pointer to the RefBase object.
1250 * @note `nullptr` will be returned if the managed object has been
1251 * deallocated.
1252 */
1253 T *GetRefPtr() const;
1254
1255 /**
1256 * @brief Gets the count of weak references in a WeakRefCounter object.
1257 *
1258 * The value indicates how many wptrs share the same WeakRefCounter object.
1259 *
1260 * @return Count of weak references.
1261 * @note Only for test.
1262 */
GetWeakRefCount()1263 inline int GetWeakRefCount() const
1264 {
1265 return refs_->GetWeakRefCount();
1266 }
1267
1268 /**
1269 * @brief Attempts to increment the count of strong references in
1270 * the managed object.
1271 *
1272 * @return `true` if the increment is successful; `false` otherwise.
1273 * @note Avoid using this function independently. Use `promote()` instead.
1274 */
AttemptIncStrongRef(const void * objectId)1275 inline bool AttemptIncStrongRef(const void *objectId) const
1276 {
1277 return refs_->AttemptIncStrongRef(objectId);
1278 }
1279
1280 /**
1281 * @brief Promotes a wptr to an sptr.
1282 *
1283 * This function will create an sptr object based on the object
1284 * managed by this wptr.
1285 *
1286 * @note The original weak reference will be retained.
1287 * If the promotion fails, a "null sptr" will be returned.
1288 */
1289 const sptr<T> promote() const;
1290
1291 ~wptr();
1292
1293 private:
1294 WeakRefCounter *refs_ = nullptr; // Pointer to the corresponding WeakRefCounter object
1295 };
1296
1297 template <typename T>
GetRefPtr()1298 inline T *wptr<T>::GetRefPtr() const
1299 {
1300 return (refs_ != nullptr) ? reinterpret_cast<T *>(refs_->GetRefPtr()) : nullptr;
1301 }
1302
1303 template <typename T>
wptr()1304 wptr<T>::wptr()
1305 {
1306 refs_ = nullptr;
1307 }
1308
1309 template <typename T>
wptr(T * other)1310 wptr<T>::wptr(T *other)
1311 {
1312 if (other != nullptr) {
1313 refs_ = other->CreateWeakRef(other);
1314 if (refs_ != nullptr) {
1315 refs_->IncWeakRefCount(this);
1316 }
1317 } else {
1318 refs_ = nullptr;
1319 }
1320 }
1321
1322 template <typename T>
wptr(const wptr<T> & other)1323 wptr<T>::wptr(const wptr<T> &other)
1324 {
1325 refs_ = other.refs_;
1326 if (refs_ != nullptr) {
1327 refs_->IncWeakRefCount(this);
1328 }
1329 }
1330
1331 template <typename T>
wptr(const sptr<T> & other)1332 wptr<T>::wptr(const sptr<T> &other)
1333 {
1334 if (other.GetRefPtr() != nullptr) {
1335 refs_ = other->CreateWeakRef(other.GetRefPtr());
1336 if (refs_ != nullptr) {
1337 refs_->IncWeakRefCount(this);
1338 }
1339 }
1340 }
1341
1342 template <typename T>
1343 template <typename O>
wptr(const wptr<O> & other)1344 wptr<T>::wptr(const wptr<O> &other)
1345 {
1346 refs_ = other.refs_;
1347 if (refs_ != nullptr) {
1348 refs_->IncWeakRefCount(this);
1349 }
1350 }
1351
1352 template <typename T>
1353 template <typename O>
wptr(const sptr<O> & other)1354 wptr<T>::wptr(const sptr<O> &other)
1355 {
1356 if (other.GetRefPtr() != nullptr) {
1357 refs_ = other->CreateWeakRef(other.GetRefPtr());
1358 if (refs_ != nullptr) {
1359 refs_->IncWeakRefCount(this);
1360 }
1361 }
1362 }
1363
1364 template <typename T>
1365 wptr<T> &wptr<T>::operator=(T *other)
1366 {
1367 WeakRefCounter *newWeakRef = nullptr;
1368 if (other != nullptr) {
1369 newWeakRef = other->CreateWeakRef(other);
1370 if (newWeakRef != nullptr) {
1371 newWeakRef->IncWeakRefCount(this);
1372 }
1373 }
1374
1375 if (refs_ != nullptr) {
1376 refs_->DecWeakRefCount(this);
1377 }
1378
1379 refs_ = newWeakRef;
1380 return *this;
1381 }
1382
1383 template <typename T>
1384 template <typename O>
1385 wptr<T> &wptr<T>::operator=(O *other)
1386 {
1387 T *object = reinterpret_cast<T *>(other);
1388 WeakRefCounter *newWeakRef = nullptr;
1389 if (object != nullptr) {
1390 newWeakRef = object->CreateWeakRef(object);
1391 if (newWeakRef != nullptr) {
1392 newWeakRef->IncWeakRefCount(this);
1393 }
1394 }
1395
1396 if (refs_ != nullptr) {
1397 refs_->DecWeakRefCount(this);
1398 }
1399
1400 refs_ = newWeakRef;
1401 return *this;
1402 }
1403
1404 template <typename T>
1405 inline wptr<T> &wptr<T>::operator=(const wptr<T> &other)
1406 {
1407 if (other.refs_ != nullptr) {
1408 other.refs_->IncWeakRefCount(this);
1409 }
1410
1411 if (refs_ != nullptr) {
1412 refs_->DecWeakRefCount(this);
1413 }
1414
1415 refs_ = other.refs_;
1416 return *this;
1417 }
1418
1419 template <typename T>
1420 inline wptr<T> &wptr<T>::operator=(const sptr<T> &other)
1421 {
1422 WeakRefCounter *newWeakRef = nullptr;
1423 if (other.GetRefPtr() != nullptr) {
1424 newWeakRef = other->CreateWeakRef(other.GetRefPtr());
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 template <typename O>
1440 wptr<T> &wptr<T>::operator=(const wptr<O> &other)
1441 {
1442 if (other.refs_ != nullptr) {
1443 other.refs_->IncWeakRefCount(this);
1444 }
1445
1446 if (refs_ != nullptr) {
1447 refs_->DecWeakRefCount(this);
1448 }
1449
1450 refs_ = other.refs_;
1451 return *this;
1452 }
1453
1454 template <typename T>
1455 template <typename O>
1456 wptr<T> &wptr<T>::operator=(const sptr<O> &other)
1457 {
1458 WeakRefCounter *newWeakRef = nullptr;
1459 if (other.GetRefPtr() != nullptr) {
1460 newWeakRef = other->CreateWeakRef(other.GetRefPtr());
1461 if (newWeakRef != nullptr) {
1462 newWeakRef->IncWeakRefCount(this);
1463 }
1464 }
1465
1466 if (refs_ != nullptr) {
1467 refs_->DecWeakRefCount(this);
1468 }
1469
1470 refs_ = newWeakRef;
1471 return *this;
1472 }
1473
1474 template <typename T>
1475 inline bool wptr<T>::operator==(const T *other) const
1476 {
1477 return GetRefPtr() == other;
1478 }
1479
1480 template <typename T>
1481 inline bool wptr<T>::operator==(const wptr<T> &other) const
1482 {
1483 return GetRefPtr() == other.GetRefPtr();
1484 }
1485
1486 template <typename T>
1487 inline bool wptr<T>::operator==(const sptr<T> &other) const
1488 {
1489 return GetRefPtr() == other.GetRefPtr();
1490 }
1491
1492 template <typename T>
promote()1493 inline const sptr<T> wptr<T>::promote() const
1494 {
1495 return sptr<T>(refs_, true);
1496 }
1497
1498 template <typename T>
~wptr()1499 inline wptr<T>::~wptr()
1500 {
1501 if (refs_ != nullptr) {
1502 refs_->DecWeakRefCount(this);
1503 }
1504 }
1505
1506 } // namespace OHOS
1507
1508 #endif
1509
1510 /**@}*/
1511