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